1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
27
28 #include <iostream>
29
30 #include <com/sun/star/embed/ElementModes.hpp>
31 #include <com/sun/star/embed/XStorage.hpp>
32 #include <unotools/ucbstreamhelper.hxx>
33
34 #include <algorithm>
35
36 #include <map>
37 #include <set>
38
39 #include <hintids.hxx>
40 #include <string.h> // memcpy()
41 #include <osl/endian.h>
42 #include <docsh.hxx>
43
44 #define _SVSTDARR_BOOLS
45 #include <svl/svstdarr.hxx>
46
47 #include <unotools/fltrcfg.hxx>
48 #include <vcl/salbtype.hxx>
49 #include <sot/storage.hxx>
50 #include <svl/zformat.hxx>
51 #include <sfx2/docinf.hxx>
52 #include <editeng/tstpitem.hxx>
53 #include <svx/svdmodel.hxx>
54 #include <svx/svdpage.hxx>
55 #include <editeng/hyznitem.hxx>
56 #include <editeng/langitem.hxx>
57 #include <filter/msfilter/msoleexp.hxx>
58 #include <filter/msfilter/msocximex.hxx>
59 #include <editeng/lrspitem.hxx>
60 #include <editeng/ulspitem.hxx>
61 #include <editeng/boxitem.hxx>
62 #include <editeng/brshitem.hxx>
63 #include <swtypes.hxx>
64 #include <swrect.hxx>
65 #include <swtblfmt.hxx>
66 #include <txatbase.hxx>
67 #include <fmtcntnt.hxx>
68 #include <fmtpdsc.hxx>
69 #include <fmtrowsplt.hxx>
70 #include <frmatr.hxx>
71 #include <doc.hxx>
72 #include <docary.hxx>
73 #include <pam.hxx>
74 #include <ndtxt.hxx>
75 #include <shellio.hxx>
76 #include <docstat.hxx>
77 #include <pagedesc.hxx>
78 #include <IMark.hxx>
79 #include <swtable.hxx>
80 #include <wrtww8.hxx>
81 #include <ww8par.hxx>
82 #include <fltini.hxx>
83 #include <swmodule.hxx>
84 #include <section.hxx>
85 #include <swfltopt.hxx>
86 #include <fmtinfmt.hxx>
87 #include <txtinet.hxx>
88 #include <fmturl.hxx>
89 #include <fesh.hxx>
90 #include <svtools/imap.hxx>
91 #include <svtools/imapobj.hxx>
92 #include <tools/urlobj.hxx>
93 #include <mdiexp.hxx> // Progress
94 #include <statstr.hrc> // ResId fuer Statusleiste
95 #include <fmtline.hxx>
96 #include <fmtfsize.hxx>
97 #include <comphelper/extract.hxx>
98 #include <comphelper/stlunosequence.hxx>
99 #include <writerfilter/doctok/sprmids.hxx>
100
101 #include "writerhelper.hxx"
102 #include "writerwordglue.hxx"
103 #include "ww8attributeoutput.hxx"
104
105 #include <IDocumentMarkAccess.hxx>
106 #include <xmloff/odffields.hxx>
107
108 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
109 #include <com/sun/star/document/XDocumentProperties.hpp>
110
111 #include "dbgoutsw.hxx"
112
113 #include <sfx2/docfile.hxx>
114 #include <sfx2/request.hxx>
115 #include <sfx2/frame.hxx>
116 #include <svl/stritem.hxx>
117 #include <unotools/tempfile.hxx>
118 #include <filter/msfilter/mscodec.hxx>
119 #include <filter/msfilter/svxmsbas.hxx>
120 #include <osl/time.h>
121 #include <rtl/random.h>
122 #include "WW8Sttbf.hxx"
123 #include <editeng/charrotateitem.hxx>
124 #include "WW8FibData.hxx"
125 #include "numrule.hxx"
126
127 #include <boost/scoped_ptr.hpp>
128
129
130 using namespace sw::util;
131 using namespace sw::types;
132
133 /** FKP - Formatted disK Page
134 */
135 class WW8_WrFkp
136 {
137 sal_uInt8* pFkp; // gesamter Fkp ( zuerst nur FCs und Sprms )
138 sal_uInt8* pOfs; // Pointer auf Offset-Bereich, spaeter nach pFkp kopiert
139 ePLCFT ePlc;
140 short nStartGrp; // ab hier grpprls
141 short nOldStartGrp;
142 sal_uInt8 nItemSize;
143 sal_uInt8 nIMax; // Anzahl der Eintrags-Paare
144 sal_uInt8 nOldVarLen;
145 sal_uInt8 nMark;
146 bool bCombined; // true : Einfuegen verboten
147
148 sal_uInt8 SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms );
149 public:
150 WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8);
151 ~WW8_WrFkp();
152 bool Append( WW8_FC nEndFc, sal_uInt16 nVarLen = 0, const sal_uInt8* pSprms = 0 );
153 bool Combine();
154 void Write( SvStream& rStrm, SwWW8WrGrf& rGrf );
155
IsEqualPos(WW8_FC nEndFc) const156 bool IsEqualPos(WW8_FC nEndFc) const
157 { return !bCombined && nIMax && nEndFc == ((sal_Int32*)pFkp)[nIMax]; }
158 void MergeToNew( short& rVarLen, sal_uInt8 *& pNewSprms );
IsEmptySprm() const159 bool IsEmptySprm() const
160 { return !bCombined && nIMax && !nOldVarLen; }
SetNewEnd(WW8_FC nEnd)161 void SetNewEnd( WW8_FC nEnd )
162 { ((sal_Int32*)pFkp)[nIMax] = nEnd; }
163
164 #ifdef __WW8_NEEDS_COPY
165 WW8_FC GetStartFc() const;
166 WW8_FC GetEndFc() const;
167 #else
GetStartFc() const168 WW8_FC GetStartFc() const { return ((sal_Int32*)pFkp)[0]; };
GetEndFc() const169 WW8_FC GetEndFc() const { return ((sal_Int32*)pFkp)[nIMax]; };
170 #endif // defined __WW8_NEEDS_COPY
171
172 sal_uInt8 *CopyLastSprms(sal_uInt8 &rLen, bool bVer8);
173 };
174
175
176 // -------------------------------------------------------------------------
177 // class WW8_WrPc sammelt alle Piece-Eintraege fuer ein Piece
178 // -------------------------------------------------------------------------
179
180 class WW8_WrPc
181 {
182 WW8_CP nStartCp; // Start ZeichenPosition vom Text
183 WW8_FC nStartFc; // Start File Position vom Text
184 sal_uInt16 nStatus; // Absatzende im Piece ?
185
186 public:
WW8_WrPc(WW8_FC nSFc,WW8_CP nSCp)187 WW8_WrPc(WW8_FC nSFc, WW8_CP nSCp )
188 : nStartCp( nSCp ), nStartFc( nSFc ), nStatus( 0x0040 )
189 {}
190
SetStatus()191 void SetStatus() { nStatus = 0x0050; }
GetStatus() const192 sal_uInt16 GetStatus() const { return nStatus; }
GetStartCp() const193 WW8_CP GetStartCp() const { return nStartCp; }
GetStartFc() const194 WW8_FC GetStartFc() const { return nStartFc; }
195 };
196
197 typedef std::map<String,long> BKMKNames;
198 typedef BKMKNames::iterator BKMKNmItr;
199 typedef std::pair<bool,String> BKMK;
200 typedef std::pair<long,BKMK> BKMKCP;
201 typedef std::multimap<long,BKMKCP*> BKMKCPs;
202 typedef BKMKCPs::iterator CPItr;
203
204 class WW8_WrtBookmarks
205 {
206 private:
207 BKMKCPs aSttCps,aEndCps;
208 BKMKNames maSwBkmkNms;
209 WW8_WrtBookmarks(const WW8_WrtBookmarks&);
210 WW8_WrtBookmarks& operator=(const WW8_WrtBookmarks&);
211
212 public:
213 WW8_WrtBookmarks();
214 ~WW8_WrtBookmarks();
215 void Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark* pBkmk=NULL );
216 void Write( WW8Export& rWrt );
217 void MoveFieldMarks(sal_uLong nFrom,sal_uLong nTo);
218 };
219
WW8_WrtBookmarks()220 WW8_WrtBookmarks::WW8_WrtBookmarks()
221 {}
222
~WW8_WrtBookmarks()223 WW8_WrtBookmarks::~WW8_WrtBookmarks()
224 {
225 CPItr aEnd = aSttCps.end();
226 for (CPItr aItr = aSttCps.begin();aItr!=aEnd;aItr++)
227 {
228 if (aItr->second)
229 {
230 delete aItr->second;
231 aItr->second = NULL;
232 }
233 }
234 }
235
Append(WW8_CP nStartCp,const String & rNm,const::sw::mark::IMark *)236 void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark*)
237 {
238 std::pair<BKMKNmItr,bool> aResult = maSwBkmkNms.insert(std::pair<String,long>(rNm,0L));
239 if (aResult.second)
240 {
241 BKMK aBK(false,rNm);
242 BKMKCP* pBKCP = new BKMKCP((long)nStartCp,aBK);
243 aSttCps.insert(std::pair<long,BKMKCP*>(nStartCp,pBKCP));
244 aResult.first->second = (long)nStartCp;
245 }
246 else
247 {
248 std::pair<CPItr,CPItr> aRange = aSttCps.equal_range(aResult.first->second);
249 for (CPItr aItr = aRange.first;aItr != aRange.second;aItr++)
250 {
251 if (aItr->second && aItr->second->second.second == rNm)
252 {
253 if (aItr->second->second.first)
254 nStartCp--;
255 aItr->second->first = (long)nStartCp;
256 break;
257 }
258 }
259 }
260 }
261
Write(WW8Export & rWrt)262 void WW8_WrtBookmarks::Write( WW8Export& rWrt)
263 {
264 if (!aSttCps.size())
265 return;
266 CPItr aItr;
267 long n;
268 std::vector<String> aNames;
269 SvMemoryStream aTempStrm1(65535,65535);
270 SvMemoryStream aTempStrm2(65535,65535);
271 for (aItr = aSttCps.begin();aItr!=aSttCps.end();aItr++)
272 {
273 if (aItr->second)
274 {
275 aEndCps.insert(std::pair<long,BKMKCP*>(aItr->second->first,aItr->second));
276 aNames.push_back(aItr->second->second.second);
277 SwWW8Writer::WriteLong( aTempStrm1, aItr->first);
278 }
279 }
280
281 aTempStrm1.Seek(0L);
282 for (aItr = aEndCps.begin(), n = 0;aItr != aEndCps.end();aItr++,n++)
283 {
284 if (aItr->second)
285 {
286 aItr->second->first = n;
287 SwWW8Writer::WriteLong( aTempStrm2, aItr->first);
288 }
289 }
290
291 aTempStrm2.Seek(0L);
292 rWrt.WriteAsStringTable(aNames, rWrt.pFib->fcSttbfbkmk,rWrt.pFib->lcbSttbfbkmk);
293 SvStream& rStrm = rWrt.bWrtWW8 ? *rWrt.pTableStrm : rWrt.Strm();
294 rWrt.pFib->fcPlcfbkf = rStrm.Tell();
295 rStrm<<aTempStrm1;
296 SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
297 for (aItr = aSttCps.begin();aItr!=aSttCps.end();aItr++)
298 {
299 if (aItr->second)
300 {
301 SwWW8Writer::WriteLong(rStrm, aItr->second->first);
302 }
303 }
304 rWrt.pFib->lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->fcPlcfbkf;
305 rWrt.pFib->fcPlcfbkl = rStrm.Tell();
306 rStrm<<aTempStrm2;
307 SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
308 rWrt.pFib->lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->fcPlcfbkl;
309 }
310
MoveFieldMarks(sal_uLong nFrom,sal_uLong nTo)311 void WW8_WrtBookmarks::MoveFieldMarks(sal_uLong nFrom,sal_uLong nTo)
312 {
313 std::pair<CPItr,CPItr> aRange = aSttCps.equal_range(nFrom);
314 CPItr aItr = aRange.first;
315 while (aItr != aRange.second)
316 {
317 if (aItr->second)
318 {
319 if (aItr->second->first == (long)nFrom)
320 {
321 aItr->second->second.first = true;
322 aItr->second->first = nTo;
323 }
324 aSttCps.insert(std::pair<long,BKMKCP*>(nTo,aItr->second));
325 aItr->second = NULL;
326 aRange = aSttCps.equal_range(nFrom);
327 aItr = aRange.first;
328 continue;
329 }
330 aItr++;
331 }
332 }
333
334 #define ANZ_DEFAULT_STYLES 16
335
336 // die Namen der StorageStreams
337 #define sMainStream CREATE_CONST_ASC("WordDocument")
338 #define sCompObj CREATE_CONST_ASC("\1CompObj")
339
340
341 SV_IMPL_VARARR( WW8Bytes, sal_uInt8 )
342 SV_IMPL_PTRARR( WW8_WrFkpPtrs, WW8_FkpPtr )
343
344 typedef WW8_WrPc* WW8_WrPcPtr;
345 SV_DECL_PTRARR_DEL( WW8_WrPcPtrs, WW8_WrPcPtr, 4, 4 )
SV_IMPL_PTRARR(WW8_WrPcPtrs,WW8_WrPcPtr)346 SV_IMPL_PTRARR( WW8_WrPcPtrs, WW8_WrPcPtr )
347
348 static void WriteDop( WW8Export& rWrt )
349 {
350 WW8Dop& rDop = *rWrt.pDop;
351
352 // i#78951#, store the value of unknown compatability options
353 rDop.SetCompatabilityOptions( rWrt.pDoc->Getn32DummyCompatabilityOptions1());
354 rDop.SetCompatabilityOptions2( rWrt.pDoc->Getn32DummyCompatabilityOptions2());
355
356 rDop.fNoLeading = !rWrt.pDoc->get(IDocumentSettingAccess::ADD_EXT_LEADING);
357 rDop.fUsePrinterMetrics = !rWrt.pDoc->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE);
358
359 // default TabStop schreiben
360 const SvxTabStopItem& rTabStop =
361 DefaultItemGet<SvxTabStopItem>(*rWrt.pDoc, RES_PARATR_TABSTOP);
362 rDop.dxaTab = (sal_uInt16)rTabStop[0].GetTabPos();
363
364
365 // Werte aus der DocStatistik (werden aufjedenfall fuer die
366 // DocStat-Felder benoetigt!)
367 rDop.fWCFtnEdn = true; // because they are included in StarWriter
368
369 const SwDocStat& rDStat = rWrt.pDoc->GetDocStat();
370 rDop.cWords = rDStat.nWord;
371 rDop.cCh = rDStat.nChar;
372 rDop.cPg = static_cast< sal_Int16 >(rDStat.nPage);
373 rDop.cParas = rDStat.nPara;
374 rDop.cLines = rDStat.nPara;
375
376 SwDocShell *pDocShell(rWrt.pDoc->GetDocShell());
377 DBG_ASSERT(pDocShell, "no SwDocShell");
378 uno::Reference<document::XDocumentProperties> xDocProps;
379 uno::Reference<beans::XPropertySet> xProps;
380 if (pDocShell) {
381 uno::Reference<lang::XComponent> xModelComp(pDocShell->GetModel(),
382 uno::UNO_QUERY);
383 xProps = uno::Reference<beans::XPropertySet>(xModelComp,
384 uno::UNO_QUERY);
385 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
386 xModelComp, uno::UNO_QUERY_THROW);
387 xDocProps = xDPS->getDocumentProperties();
388 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
389
390 rDop.lKeyProtDoc = pDocShell->GetModifyPasswordHash();
391 }
392
393 if ((rWrt.pSepx && rWrt.pSepx->DocumentIsProtected()) ||
394 rDop.lKeyProtDoc != 0)
395 {
396 rDop.fProtEnabled = 1;
397 }
398 else
399 {
400 rDop.fProtEnabled = 0;
401 }
402
403 if (!xDocProps.is()) {
404 rDop.dttmCreated = rDop.dttmRevised = rDop.dttmLastPrint = 0x45FBAC69;
405 } else {
406 ::util::DateTime uDT = xDocProps->getCreationDate();
407 Date aD(uDT.Day, uDT.Month, uDT.Year);
408 Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
409 rDop.dttmCreated = sw::ms::DateTime2DTTM(DateTime(aD,aT));
410 uDT = xDocProps->getModificationDate();
411 Date aD2(uDT.Day, uDT.Month, uDT.Year);
412 Time aT2(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
413 rDop.dttmRevised = sw::ms::DateTime2DTTM(DateTime(aD2,aT2));
414 uDT = xDocProps->getPrintDate();
415 Date aD3(uDT.Day, uDT.Month, uDT.Year);
416 Time aT3(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
417 rDop.dttmLastPrint = sw::ms::DateTime2DTTM(DateTime(aD3,aT3));
418
419 }
420
421 // auch damit werden die DocStat-Felder in Kopf-/Fusszeilen nicht korrekt
422 // berechnet.
423 // ( we do not have this fields! )
424
425 // und noch fuer die Header und Footers
426 rDop.cWordsFtnEnd = rDStat.nWord;
427 rDop.cChFtnEdn = rDStat.nChar;
428 rDop.cPgFtnEdn = (sal_Int16)rDStat.nPage;
429 rDop.cParasFtnEdn = rDStat.nPara;
430 rDop.cLinesFtnEdn = rDStat.nPara;
431
432 rDop.fDontUseHTMLAutoSpacing = (rWrt.pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX) != 0);
433
434 rDop.fExpShRtn = !rWrt.pDoc->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK); // #i56856#
435
436 rDop.Write( *rWrt.pTableStrm, *rWrt.pFib );
437 }
438
GetJapanNotBeginLevel1()439 const sal_Unicode *WW8DopTypography::GetJapanNotBeginLevel1()
440 {
441 static const sal_Unicode aJapanNotBeginLevel1[nMaxFollowing] =
442 //Japanese Level 1
443 {
444 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
445 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
446 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
447 0x300f, 0x3011, 0x3015, 0x309b, 0x309c, 0x309d, 0x309e, 0x30fb,
448 0x30fd, 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a,
449 0xff1b, 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65,
450 0xff9e, 0xff9f, 0xffe0
451 };
452 return &aJapanNotBeginLevel1[0];
453 }
454
GetJapanNotEndLevel1()455 const sal_Unicode *WW8DopTypography::GetJapanNotEndLevel1()
456 {
457 static const sal_Unicode aJapanNotEndLevel1[nMaxLeading] =
458 //Japanese Level 1
459 {
460 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
461 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
462 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
463 };
464 return &aJapanNotEndLevel1[0];
465 }
466
lcl_CmpBeginEndChars(const rtl::OUString & rSWStr,const sal_Unicode * pMSStr,int nMSStrByteLen)467 int lcl_CmpBeginEndChars( const rtl::OUString& rSWStr,
468 const sal_Unicode* pMSStr, int nMSStrByteLen )
469 {
470 nMSStrByteLen /= sizeof( sal_Unicode );
471 if( nMSStrByteLen > rSWStr.getLength() )
472 nMSStrByteLen = rSWStr.getLength()+1;
473 nMSStrByteLen *= sizeof( sal_Unicode );
474
475 return memcmp( rSWStr.getStr(), pMSStr, nMSStrByteLen );
476 }
477
478 /*
479 Converts the OOo Asian Typography into a best fit match for Microsoft
480 Asian typography. This structure is actually dumped to disk within the
481 Dop Writer. Assumption is that rTypo is cleared to 0 on entry
482 */
ExportDopTypography(WW8DopTypography & rTypo)483 void WW8Export::ExportDopTypography(WW8DopTypography &rTypo)
484 {
485 static const sal_Unicode aLangNotBegin[4][WW8DopTypography::nMaxFollowing]=
486 {
487 //Japanese Level 1
488 {
489 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
490 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
491 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
492 0x300f, 0x3011, 0x3015, 0x3041, 0x3043, 0x3045, 0x3047, 0x3049,
493 0x3063, 0x3083, 0x3085, 0x3087, 0x308e, 0x309b, 0x309c, 0x309d,
494 0x309e, 0x30a1, 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30c3, 0x30e3,
495 0x30e5, 0x30e7, 0x30ee, 0x30f5, 0x30f6, 0x30fb, 0x30fc, 0x30fd,
496 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b,
497 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65, 0xff67,
498 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
499 0xff70, 0xff9e, 0xff9f, 0xffe0
500 },
501 //Simplified Chinese
502 {
503 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
504 0x007d, 0x00a8, 0x00b7, 0x02c7, 0x02c9, 0x2015, 0x2016, 0x2019,
505 0x201d, 0x2026, 0x2236, 0x3001, 0x3002, 0x3003, 0x3005, 0x3009,
506 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x3017, 0xff01, 0xff02,
507 0xff07, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
508 0xff40, 0xff5c, 0xff5d, 0xff5e, 0xffe0
509 },
510 //Korean
511 {
512 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
513 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2032, 0x2033,
514 0x2103, 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0xff01,
515 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
516 0xff5d, 0xffe0
517 },
518 //Traditional Chinese
519 {
520 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
521 0x007d, 0x00a2, 0x00b7, 0x2013, 0x2014, 0x2019, 0x201d, 0x2022,
522 0x2025, 0x2026, 0x2027, 0x2032, 0x2574, 0x3001, 0x3002, 0x3009,
523 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x301e, 0xfe30, 0xfe31,
524 0xfe33, 0xfe34, 0xfe36, 0xfe38, 0xfe3a, 0xfe3c, 0xfe3e, 0xfe40,
525 0xfe42, 0xfe44, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55,
526 0xfe56, 0xfe57, 0xfe5a, 0xfe5c, 0xfe5e, 0xff01, 0xff09, 0xff0c,
527 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff5c, 0xff5d, 0xff64
528 },
529 };
530
531 static const sal_Unicode aLangNotEnd[4][WW8DopTypography::nMaxLeading] =
532 {
533 //Japanese Level 1
534 {
535 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
536 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
537 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
538 },
539 //Simplified Chinese
540 {
541 0x0028, 0x005b, 0x007b, 0x00b7, 0x2018, 0x201c, 0x3008, 0x300a,
542 0x300c, 0x300e, 0x3010, 0x3014, 0x3016, 0xff08, 0xff0e, 0xff3b,
543 0xff5b, 0xffe1, 0xffe5
544 },
545 //Korean
546 {
547 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c,
548 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04, 0xff08,
549 0xff3b, 0xff5b, 0xffe6
550 },
551 //Traditional Chinese
552 {
553 0x0028, 0x005b, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c, 0x2035,
554 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0x301d, 0xfe35,
555 0xfe37, 0xfe39, 0xfe3b, 0xfe3d, 0xfe3f, 0xfe41, 0xfe43, 0xfe59,
556 0xfe5b, 0xfe5d, 0xff08, 0xff5b
557 },
558 };
559
560 const i18n::ForbiddenCharacters *pForbidden = 0;
561 const i18n::ForbiddenCharacters *pUseMe = 0;
562 sal_uInt8 nUseReserved=0;
563 int nNoNeeded=0;
564 /*
565 Now we have some minor difficult issues, to wit...
566 a. MicroSoft Office can only store one set of begin and end characters in
567 a given document, not one per language.
568 b. StarOffice has only a concept of one set of begin and end characters for
569 a given language, i.e. not the two levels of kinsoku in japanese
570
571 What is unknown as yet is if our default begin and end chars for
572 japanese, chinese tradition, chinese simplified and korean are different
573 in Word and Writer. I already suspect that they are different between
574 different version of word itself.
575
576 So what have come up with is to simply see if any of the four languages
577 in OOo have been changed away from OUR defaults, and if one has then
578 export that. If more than one has in the future we may hack in something
579 which examines our document properties to see which language is used the
580 most and choose that, for now we choose the first and throw an ASSERT.
581 */
582
583 /*Our default Japanese Level is 2, this is a special MS hack to set this*/
584 rTypo.reserved2 = 1;
585
586 for (rTypo.reserved1=8;rTypo.reserved1>0;rTypo.reserved1-=2)
587 {
588 if (0 != (pForbidden = pDoc->getForbiddenCharacters(rTypo.GetConvertedLang(),
589 false)))
590 {
591 int nIdx = (rTypo.reserved1-2)/2;
592 if( lcl_CmpBeginEndChars( pForbidden->endLine,
593 aLangNotEnd[ nIdx ], sizeof(aLangNotEnd[ nIdx ]) ) ||
594 lcl_CmpBeginEndChars( pForbidden->beginLine,
595 aLangNotBegin[ nIdx ], sizeof(aLangNotBegin[ nIdx ]) ) )
596 {
597 //One exception for Japanese, if it matches a level 1 we
598 //can use one extra flag for that, rather than use a custom
599 if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
600 {
601 if (
602 !lcl_CmpBeginEndChars
603 (
604 pForbidden->endLine,
605 rTypo.GetJapanNotEndLevel1(),
606 rTypo.nMaxLeading * sizeof(sal_Unicode)
607 )
608 &&
609 !lcl_CmpBeginEndChars
610 (
611 pForbidden->beginLine,
612 rTypo.GetJapanNotBeginLevel1(),
613 rTypo.nMaxFollowing * sizeof(sal_Unicode)
614 )
615 )
616 {
617 rTypo.reserved2 = 0;
618 continue;
619 }
620 }
621
622 if (!pUseMe)
623 {
624 pUseMe = pForbidden;
625 nUseReserved = rTypo.reserved1;
626 rTypo.iLevelOfKinsoku = 2;
627 }
628 nNoNeeded++;
629 }
630 }
631 }
632
633 ASSERT( nNoNeeded<=1, "Example of unexportable forbidden chars" );
634 rTypo.reserved1=nUseReserved;
635 if (rTypo.iLevelOfKinsoku)
636 {
637 rTypo.cchFollowingPunct = msword_cast<sal_Int16>
638 (pUseMe->beginLine.getLength());
639 if (rTypo.cchFollowingPunct > WW8DopTypography::nMaxFollowing - 1)
640 rTypo.cchFollowingPunct = WW8DopTypography::nMaxFollowing - 1;
641
642 rTypo.cchLeadingPunct = msword_cast<sal_Int16>
643 (pUseMe->endLine.getLength());
644 if (rTypo.cchLeadingPunct > WW8DopTypography::nMaxLeading - 1)
645 rTypo.cchLeadingPunct = WW8DopTypography::nMaxLeading -1;
646
647 memcpy(rTypo.rgxchFPunct,pUseMe->beginLine.getStr(),
648 (rTypo.cchFollowingPunct+1)*2);
649
650 memcpy(rTypo.rgxchLPunct,pUseMe->endLine.getStr(),
651 (rTypo.cchLeadingPunct+1)*2);
652 }
653
654 const IDocumentSettingAccess* pIDocumentSettingAccess = GetWriter().getIDocumentSettingAccess();
655
656 rTypo.fKerningPunct = pIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION);
657 rTypo.iJustification = pDoc->getCharacterCompressionType();
658 }
659
660 // HasItem ist fuer die Zusammenfassung der Doppel-Attribute
661 // Underline / WordLineMode und Box / Shadow.
662 // Es kann nur etwas gefunden werden, wenn diese Methode innerhalb
663 // der aufgerufenen Methoden WW8_SwAttrIter::OutAttr() und
664 // WW8Export::OutputItemSet() benutzt wird.
HasItem(sal_uInt16 nWhich) const665 const SfxPoolItem* MSWordExportBase::HasItem( sal_uInt16 nWhich ) const
666 {
667 const SfxPoolItem* pItem=0;
668 if (pISet)
669 {
670 // if write a EditEngine text, then the WhichIds are greater as
671 // ourer own Ids. So the Id have to translate from our into the
672 // EditEngine Range
673 nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
674 if (nWhich && SFX_ITEM_SET != pISet->GetItemState(nWhich, true, &pItem))
675 pItem = 0;
676 }
677 else if( pChpIter )
678 pItem = pChpIter->HasTextItem( nWhich );
679 else
680 {
681 ASSERT( !this, "Wo ist mein ItemSet / pChpIter ?" );
682 pItem = 0;
683 }
684 return pItem;
685 }
686
GetItem(sal_uInt16 nWhich) const687 const SfxPoolItem& MSWordExportBase::GetItem(sal_uInt16 nWhich) const
688 {
689 const SfxPoolItem* pItem;
690 if (pISet)
691 {
692 // if write a EditEngine text, then the WhichIds are greater as
693 // ourer own Ids. So the Id have to translate from our into the
694 // EditEngine Range
695 nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
696 ASSERT(nWhich != 0, "All broken, Impossible");
697 pItem = &pISet->Get(nWhich, true);
698 }
699 else if( pChpIter )
700 pItem = &pChpIter->GetItem( nWhich );
701 else
702 {
703 ASSERT( !this, "Wo ist mein ItemSet / pChpIter ?" );
704 pItem = 0;
705 }
706 return *pItem;
707 }
708
709 //------------------------------------------------------------------------------
710
WW8_WrPlc1(sal_uInt16 nStructSz)711 WW8_WrPlc1::WW8_WrPlc1( sal_uInt16 nStructSz )
712 : aPos( 16, 16 ), nStructSiz( nStructSz )
713 {
714 nDataLen = 16 * nStructSz;
715 pData = new sal_uInt8[ nDataLen ];
716 }
717
~WW8_WrPlc1()718 WW8_WrPlc1::~WW8_WrPlc1()
719 {
720 delete[] pData;
721 }
722
Prev() const723 WW8_CP WW8_WrPlc1::Prev() const
724 {
725 sal_uInt16 nLen = aPos.Count();
726 ASSERT(nLen,"Prev called on empty list");
727 return nLen ? aPos[nLen-1] : 0;
728 }
729
Append(WW8_CP nCp,const void * pNewData)730 void WW8_WrPlc1::Append( WW8_CP nCp, const void* pNewData )
731 {
732 sal_uLong nInsPos = aPos.Count() * nStructSiz;
733 aPos.Insert( nCp, aPos.Count() );
734 if( nDataLen < nInsPos + nStructSiz )
735 {
736 sal_uInt8* pNew = new sal_uInt8[ 2 * nDataLen ];
737 memmove( pNew, pData, nDataLen );
738 delete[] pData;
739 pData = pNew;
740 nDataLen *= 2;
741 }
742 memcpy( pData + nInsPos, pNewData, nStructSiz );
743 }
744
Finish(sal_uLong nLastCp,sal_uLong nSttCp)745 void WW8_WrPlc1::Finish( sal_uLong nLastCp, sal_uLong nSttCp )
746 {
747 if( aPos.Count() )
748 {
749 aPos.Insert( nLastCp, aPos.Count() );
750 if( nSttCp )
751 for( sal_uInt16 n = 0; n < aPos.Count(); ++n )
752 aPos[ n ] -= nSttCp;
753 }
754 }
755
756
Write(SvStream & rStrm)757 void WW8_WrPlc1::Write( SvStream& rStrm )
758 {
759 sal_uInt16 i;
760 for( i = 0; i < aPos.Count(); ++i )
761 SwWW8Writer::WriteLong( rStrm, aPos[i] );
762 if( i )
763 rStrm.Write( pData, (i-1) * nStructSiz );
764 }
765
766 //------------------------------------------------------------------------------
767 // Klasse WW8_WrPlcFld fuer Felder
768 //------------------------------------------------------------------------------
769
770
Write(WW8Export & rWrt)771 bool WW8_WrPlcFld::Write( WW8Export& rWrt )
772 {
773 if( WW8_WrPlc1::Count() <= 1 )
774 return false;
775
776 WW8_FC *pfc;
777 sal_Int32 *plc;
778 switch (nTxtTyp)
779 {
780 case TXT_MAINTEXT:
781 pfc = &rWrt.pFib->fcPlcffldMom;
782 plc = &rWrt.pFib->lcbPlcffldMom;
783 break;
784 case TXT_HDFT:
785 pfc = &rWrt.pFib->fcPlcffldHdr;
786 plc = &rWrt.pFib->lcbPlcffldHdr;
787 break;
788
789 case TXT_FTN:
790 pfc = &rWrt.pFib->fcPlcffldFtn;
791 plc = &rWrt.pFib->lcbPlcffldFtn;
792 break;
793
794 case TXT_EDN:
795 pfc = &rWrt.pFib->fcPlcffldEdn;
796 plc = &rWrt.pFib->lcbPlcffldEdn;
797 break;
798
799 case TXT_ATN:
800 pfc = &rWrt.pFib->fcPlcffldAtn;
801 plc = &rWrt.pFib->lcbPlcffldAtn;
802 break;
803
804 case TXT_TXTBOX:
805 pfc = &rWrt.pFib->fcPlcffldTxbx;
806 plc = &rWrt.pFib->lcbPlcffldTxbx;
807 break;
808
809 case TXT_HFTXTBOX:
810 pfc = &rWrt.pFib->fcPlcffldHdrTxbx;
811 plc = &rWrt.pFib->lcbPlcffldHdrTxbx;
812 break;
813
814 default:
815 pfc = plc = 0;
816 break;
817 }
818
819 if( pfc && plc )
820 {
821 sal_uLong nFcStart = rWrt.pTableStrm->Tell();
822 WW8_WrPlc1::Write( *rWrt.pTableStrm );
823 *pfc = nFcStart;
824 *plc = rWrt.pTableStrm->Tell() - nFcStart;
825 }
826 return true;
827 }
828
Write(WW8Export & rWrt)829 bool WW8_WrMagicTable::Write( WW8Export& rWrt )
830 {
831 if( WW8_WrPlc1::Count() <= 1 )
832 return false;
833 sal_uLong nFcStart = rWrt.pTableStrm->Tell();
834 WW8_WrPlc1::Write( *rWrt.pTableStrm );
835 rWrt.pFib->fcPlcfTch = nFcStart;
836 rWrt.pFib->lcbPlcfTch = rWrt.pTableStrm->Tell() - nFcStart;
837 return true;
838 }
839
Append(WW8_CP nCp,sal_uLong nData)840 void WW8_WrMagicTable::Append( WW8_CP nCp, sal_uLong nData)
841 {
842 SVBT32 nLittle;
843 /*
844 Tell the undocumented table hack that everything between here and the last
845 table position is nontable text, don't do it if the previous position is
846 the same as this one, as that would be a region of 0 length
847 */
848 if ((!Count()) || (Prev() != nCp))
849 {
850 UInt32ToSVBT32(nData,nLittle);
851 WW8_WrPlc1::Append(nCp, nLittle);
852 }
853 }
854
855 //--------------------------------------------------------------------------
856
FillCount(SvStream & rStrm,sal_uLong nCount)857 void SwWW8Writer::FillCount( SvStream& rStrm, sal_uLong nCount )
858 {
859 static const sal_uInt32 aNulls[16] =
860 {
861 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 64 Byte
862 };
863
864 while (nCount > 64)
865 {
866 rStrm.Write( aNulls, 64 ); // in 64-Byte-Schritten
867 nCount -= 64;
868 }
869 rStrm.Write( aNulls, nCount ); // Rest ( 0 .. 64 Bytes ) schreiben
870 }
871
FillUntil(SvStream & rStrm,sal_uLong nEndPos)872 sal_uLong SwWW8Writer::FillUntil( SvStream& rStrm, sal_uLong nEndPos )
873 {
874 sal_uLong nCurPos = rStrm.Tell();
875 if( !nEndPos ) // nEndPos == 0 -> next Page
876 nEndPos = (nCurPos + 0x1ff) & ~0x1ffUL;
877
878 if( nEndPos > nCurPos )
879 SwWW8Writer::FillCount( rStrm, nEndPos - nCurPos );
880 #ifdef DBG_UTIL
881 else
882 ASSERT( nEndPos == nCurPos, "Falsches FillUntil()" );
883 #endif
884 return rStrm.Tell();
885 }
886
887
888 //--------------------------------------------------------------------------
889 /* */
890
WW8_WrPlcPn(WW8Export & rWr,ePLCFT ePl,WW8_FC nStartFc)891 WW8_WrPlcPn::WW8_WrPlcPn( WW8Export& rWr, ePLCFT ePl, WW8_FC nStartFc )
892 : rWrt(rWr), nFkpStartPage(0), ePlc(ePl), nMark(0)
893 {
894 WW8_FkpPtr pF = new WW8_WrFkp( ePlc, nStartFc, rWrt.bWrtWW8 );
895 aFkps.Insert( pF, aFkps.Count() );
896 }
897
~WW8_WrPlcPn()898 WW8_WrPlcPn::~WW8_WrPlcPn()
899 {
900 aFkps.DeleteAndDestroy( 0, aFkps.Count() );
901 }
902
CopyLastSprms(sal_uInt8 & rLen)903 sal_uInt8 *WW8_WrPlcPn::CopyLastSprms(sal_uInt8 &rLen)
904 {
905 WW8_FkpPtr pF = aFkps.GetObject(aFkps.Count() - 1);
906 return pF->CopyLastSprms(rLen, rWrt.bWrtWW8);
907 }
908
AppendFkpEntry(WW8_FC nEndFc,short nVarLen,const sal_uInt8 * pSprms)909 void WW8_WrPlcPn::AppendFkpEntry(WW8_FC nEndFc,short nVarLen,const sal_uInt8* pSprms)
910 {
911 WW8_FkpPtr pF = aFkps.GetObject( aFkps.Count() - 1 );
912
913 // big sprm? build the sprmPHugePapx
914 sal_uInt8* pNewSprms = (sal_uInt8*)pSprms;
915 sal_uInt8 aHugePapx[ 8 ];
916 if( rWrt.bWrtWW8 && PAP == ePlc && 488 < nVarLen )
917 {
918 sal_uInt8* p = aHugePapx;
919 *p++ = *pSprms++; // set style Id
920 *p++ = *pSprms++;
921 nVarLen -= 2;
922
923 long nDataPos = rWrt.pDataStrm->Tell();
924 SwWW8Writer::WriteShort( *rWrt.pDataStrm, nVarLen );
925 rWrt.pDataStrm->Write( pSprms, nVarLen );
926
927 Set_UInt16( p, 0x6646 ); // set SprmCode
928 Set_UInt32( p, nDataPos ); // set startpos (FC) in the datastream
929 nVarLen = static_cast< short >(p - aHugePapx);
930 pSprms = pNewSprms = aHugePapx;
931 }
932 // if append at the same FC-EndPos and there are sprms, then get the old
933 // sprms and erase it; they will append now with the new sprms
934 else if( nVarLen && pF->IsEqualPos( nEndFc ))
935 pF->MergeToNew( nVarLen, pNewSprms );
936 // has the prev EndFC an empty sprm and the current is empty too, then
937 // expand only the old EndFc to the new EndFc
938 else if( !nVarLen && pF->IsEmptySprm() )
939 {
940 pF->SetNewEnd( nEndFc );
941 return ;
942 }
943
944 bool bOk = pF->Append(nEndFc, nVarLen, pNewSprms);
945 if( !bOk )
946 {
947 pF->Combine();
948 pF = new WW8_WrFkp( ePlc, pF->GetEndFc(), rWrt.bWrtWW8 );// Anfang neuer Fkp
949 // == Ende alter Fkp
950 aFkps.Insert( pF, aFkps.Count() );
951 if( !pF->Append( nEndFc, nVarLen, pNewSprms ) )
952 {
953 ASSERT( !this, "Sprm liess sich nicht einfuegen" );
954 }
955 }
956 if( pNewSprms != pSprms ) //Merge to new has created a new block
957 delete[] pNewSprms;
958 }
959
WriteFkps()960 void WW8_WrPlcPn::WriteFkps()
961 {
962 nFkpStartPage = (sal_uInt16) ( SwWW8Writer::FillUntil( rWrt.Strm() ) >> 9 );
963
964 for( sal_uInt16 i = 0; i < aFkps.Count(); i++ )
965 aFkps.GetObject( i )->Write( rWrt.Strm(), *rWrt.pGrf );
966
967 if( CHP == ePlc )
968 {
969 rWrt.pFib->pnChpFirst = nFkpStartPage;
970 rWrt.pFib->cpnBteChp = aFkps.Count();
971 }
972 else
973 {
974 rWrt.pFib->pnPapFirst = nFkpStartPage;
975 rWrt.pFib->cpnBtePap = aFkps.Count();
976 }
977 }
978
WritePlc()979 void WW8_WrPlcPn::WritePlc()
980 {
981 sal_uLong nFcStart = rWrt.pTableStrm->Tell();
982 sal_uInt16 i;
983
984 for( i = 0; i < aFkps.Count(); i++ )
985 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
986 aFkps.GetObject( i )->GetStartFc() );
987
988 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
989 aFkps.GetObject( i - 1 )->GetEndFc() );
990
991 // fuer jedes FKP die Page ausgeben
992 if( rWrt.bWrtWW8) // fuer WW97 Long-Ausgabe
993 for ( i = 0; i < aFkps.Count(); i++)
994 SwWW8Writer::WriteLong( *rWrt.pTableStrm, i + nFkpStartPage );
995 else // fuer WW95 Short-Ausgabe
996 for ( i = 0; i < aFkps.Count(); i++)
997 SwWW8Writer::WriteShort( *rWrt.pTableStrm, i + nFkpStartPage );
998
999 if( CHP == ePlc )
1000 {
1001 rWrt.pFib->fcPlcfbteChpx = nFcStart;
1002 rWrt.pFib->lcbPlcfbteChpx = rWrt.pTableStrm->Tell() - nFcStart;
1003 }
1004 else
1005 {
1006 rWrt.pFib->fcPlcfbtePapx = nFcStart;
1007 rWrt.pFib->lcbPlcfbtePapx = rWrt.pTableStrm->Tell() - nFcStart;
1008 }
1009 }
1010
1011 //--------------------------------------------------------------------------
1012 /* */
1013
WW8_WrFkp(ePLCFT ePl,WW8_FC nStartFc,bool bWrtWW8)1014 WW8_WrFkp::WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8)
1015 : ePlc(ePl), nStartGrp(511), nOldStartGrp(511),
1016 nItemSize( ( CHP == ePl ) ? 1 : ( bWrtWW8 ? 13 : 7 )),
1017 nIMax(0), nOldVarLen(0), nMark(0), bCombined(false)
1018 {
1019 pFkp = (sal_uInt8*)new sal_Int32[128]; // 512 Byte
1020 pOfs = (sal_uInt8*)new sal_Int32[128]; // 512 Byte
1021 memset( pFkp, 0, 4 * 128 );
1022 memset( pOfs, 0, 4 * 128 );
1023 ( (sal_Int32*)pFkp )[0] = nStartFc; // 0. FC-Eintrag auf nStartFc
1024 }
1025
~WW8_WrFkp()1026 WW8_WrFkp::~WW8_WrFkp()
1027 {
1028 delete[] (sal_Int32 *)pFkp;
1029 delete[] (sal_Int32 *)pOfs;
1030 }
1031
SearchSameSprm(sal_uInt16 nVarLen,const sal_uInt8 * pSprms)1032 sal_uInt8 WW8_WrFkp::SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms )
1033 {
1034 if( 3 < nVarLen )
1035 {
1036 // if the sprms contained picture-references then never equal!
1037 for( sal_uInt8 n = static_cast< sal_uInt8 >(nVarLen - 1); 3 < n; --n )
1038 if( pSprms[ n ] == GRF_MAGIC_3 &&
1039 pSprms[ n-1 ] == GRF_MAGIC_2 &&
1040 pSprms[ n-2 ] == GRF_MAGIC_1 )
1041 return 0;
1042 }
1043
1044 short i;
1045 for( i = 0; i < nIMax; i++ )
1046 {
1047 sal_uInt8 nStart = pOfs[i * nItemSize];
1048 if( nStart )
1049 { // Hat Sprms
1050 const sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
1051 if( ( CHP == ePlc
1052 ? (*p++ == nVarLen)
1053 : (((sal_uInt16)*p++ << 1 ) == (( nVarLen+1) & 0xfffe)) )
1054 && !memcmp( p, pSprms, nVarLen ) )
1055 return nStart; // gefunden
1056 }
1057 }
1058 return 0; // nicht gefunden
1059 }
1060
CopyLastSprms(sal_uInt8 & rLen,bool bVer8)1061 sal_uInt8 *WW8_WrFkp::CopyLastSprms(sal_uInt8 &rLen, bool bVer8)
1062 {
1063 rLen=0;
1064 sal_uInt8 *pStart=0,*pRet=0;
1065
1066 if (!bCombined)
1067 pStart = pOfs;
1068 else
1069 pStart = pFkp + ( nIMax + 1 ) * 4;
1070
1071 sal_uInt8 nStart = *(pStart + (nIMax-1) * nItemSize);
1072
1073 const sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
1074
1075 if (!*p && bVer8)
1076 p++;
1077
1078 if (*p)
1079 {
1080 rLen = *p++;
1081 if (PAP == ePlc)
1082 rLen *= 2;
1083 pRet = new sal_uInt8[rLen];
1084 memcpy(pRet,p,rLen);
1085 }
1086 return pRet;
1087 }
1088
Append(WW8_FC nEndFc,sal_uInt16 nVarLen,const sal_uInt8 * pSprms)1089 bool WW8_WrFkp::Append( WW8_FC nEndFc, sal_uInt16 nVarLen, const sal_uInt8* pSprms )
1090 {
1091 ASSERT( !nVarLen || pSprms, "Item-Pointer fehlt" );
1092 ASSERT( nVarLen < ( ( ePlc == PAP ) ? 497U : 502U ), "Sprms zu lang !" );
1093
1094 if( bCombined )
1095 {
1096 ASSERT( !this, "Fkp::Append: Fkp is already combined" );
1097 return false;
1098 }
1099 sal_Int32 n = ((sal_Int32*)pFkp)[nIMax]; // letzter Eintrag
1100 if( nEndFc <= n )
1101 {
1102 ASSERT( nEndFc >= n, "+Fkp: FC rueckwaerts" );
1103 ASSERT( !nVarLen || !pSprms || nEndFc != n,
1104 "+Fkp: selber FC mehrfach benutzt" );
1105 // selber FC ohne Sprm wird ohne zu mosern ignoriert.
1106
1107 return true; // ignorieren, keinen neuen Fkp anlegen
1108 }
1109
1110 sal_uInt8 nOldP = ( nVarLen ) ? SearchSameSprm( nVarLen, pSprms ) : 0;
1111 // Kombinieren gleicher Eintraege
1112 short nOffset=0, nPos = nStartGrp;
1113 if (nVarLen && !nOldP)
1114 {
1115 nPos = PAP == ePlc
1116 ? ( 13 == nItemSize // HACK: PAP und bWrtWW8 !!
1117 ? (nStartGrp & 0xFFFE ) - nVarLen - 1
1118 : (nStartGrp - (((nVarLen + 1) & 0xFFFE)+1)) & 0xFFFE )
1119 : ((nStartGrp - nVarLen - 1) & 0xFFFE);
1120 if( nPos < 0 )
1121 return false; // Passt absolut nicht
1122 nOffset = nPos; // Offset merken (kann auch ungerade sein!)
1123 nPos &= 0xFFFE; // Pos fuer Sprms ( gerade Pos )
1124 }
1125
1126 if( (sal_uInt16)nPos <= ( nIMax + 2U ) * 4U + ( nIMax + 1U ) * nItemSize )
1127 // Passt hinter CPs und Offsets ?
1128 return false; // Nein
1129
1130 ((sal_Int32*)pFkp)[nIMax + 1] = nEndFc; // FC eintragen
1131
1132 nOldVarLen = (sal_uInt8)nVarLen;
1133 if( nVarLen && !nOldP )
1134 { // echt eintragen
1135 nOldStartGrp = nStartGrp;
1136
1137 nStartGrp = nPos;
1138 pOfs[nIMax * nItemSize] = (sal_uInt8)( nStartGrp >> 1 );
1139 // ( DatenAnfg >> 1 ) eintragen
1140 sal_uInt8 nCnt = static_cast< sal_uInt8 >(CHP == ePlc
1141 ? ( nVarLen < 256 ) ? (sal_uInt8) nVarLen : 255
1142 : ( ( nVarLen + 1 ) >> 1 ));
1143
1144 pFkp[ nOffset ] = nCnt; // DatenLaenge eintragen
1145 memcpy( pFkp + nOffset + 1, pSprms, nVarLen ); // Sprms speichern
1146 }
1147 else
1148 {
1149 // nicht echt eintragen ( keine Sprms oder Wiederholung )
1150 // DatenAnfg 0 ( keine Daten ) oder Wiederholung
1151 pOfs[nIMax * nItemSize] = nOldP;
1152 }
1153 nIMax++;
1154 return true;
1155 }
1156
Combine()1157 bool WW8_WrFkp::Combine()
1158 {
1159 if( bCombined )
1160 return false;
1161 if( nIMax )
1162 memcpy( pFkp + ( nIMax + 1 ) * 4, pOfs, nIMax * nItemSize );
1163 delete[] pOfs;
1164 pOfs = 0;
1165 ((sal_uInt8*)pFkp)[511] = nIMax;
1166 bCombined = true;
1167
1168 #if defined OSL_BIGENDIAN // Hier werden nur die FCs gedreht, die
1169 sal_uInt16 i; // Sprms muessen an anderer Stelle gedreht
1170 // werden
1171 sal_uInt32* p;
1172 for( i = 0, p = (sal_uInt32*)pFkp; i <= nIMax; i++, p++ )
1173 *p = SWAPLONG( *p );
1174 #endif // ifdef OSL_BIGENDIAN
1175
1176 return true;
1177 }
1178
Write(SvStream & rStrm,SwWW8WrGrf & rGrf)1179 void WW8_WrFkp::Write( SvStream& rStrm, SwWW8WrGrf& rGrf )
1180 {
1181 Combine(); // Falls noch nicht Combined
1182
1183 sal_uInt8* p; // Suche Magic fuer nPicLocFc
1184 sal_uInt8* pEnd = pFkp + nStartGrp;
1185 for( p = pFkp + 511 - 4; p >= pEnd; p-- )
1186 {
1187 if( *p != GRF_MAGIC_1 ) // Suche nach Signatur 0x12 0x34 0x56 0xXX
1188 continue;
1189 if( *(p+1) != GRF_MAGIC_2 )
1190 continue;
1191 if( *(p+2) != GRF_MAGIC_3 )
1192 continue;
1193
1194 SVBT32 nPos; // Signatur gefunden
1195 UInt32ToSVBT32( rGrf.GetFPos(), nPos ); // FilePos der Grafik
1196 memcpy( p, nPos, 4 ); // Patche FilePos ueber Signatur
1197 }
1198 rStrm.Write( pFkp, 512 );
1199 }
1200
MergeToNew(short & rVarLen,sal_uInt8 * & rpNewSprms)1201 void WW8_WrFkp::MergeToNew( short& rVarLen, sal_uInt8 *& rpNewSprms )
1202 {
1203 sal_uInt8 nStart = pOfs[ (nIMax-1) * nItemSize ];
1204 if( nStart )
1205 { // Hat Sprms
1206 sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
1207
1208 // old and new equal? Then copy only one into the new sprms
1209 if( nOldVarLen == rVarLen && !memcmp( p+1, rpNewSprms, nOldVarLen ))
1210 {
1211 sal_uInt8* pNew = new sal_uInt8[ nOldVarLen ];
1212 memcpy( pNew, p+1, nOldVarLen );
1213 rpNewSprms = pNew;
1214 }
1215 else
1216 {
1217 sal_uInt8* pNew = new sal_uInt8[ nOldVarLen + rVarLen ];
1218 memcpy( pNew, p+1, nOldVarLen );
1219 memcpy( pNew + nOldVarLen, rpNewSprms, rVarLen );
1220
1221 rpNewSprms = pNew;
1222 rVarLen = rVarLen + nOldVarLen;
1223 }
1224 --nIMax;
1225 // if this sprms dont used from others, remove it
1226 bool bFnd = false;
1227 for (sal_uInt16 n = 0; n < nIMax; ++n)
1228 {
1229 if (nStart == pOfs[n * nItemSize])
1230 {
1231 bFnd = true;
1232 break;
1233 }
1234 }
1235 if (!bFnd)
1236 {
1237 nStartGrp = nOldStartGrp;
1238 memset( p, 0, nOldVarLen+1 );
1239 }
1240 }
1241 }
1242
1243 #ifdef __WW8_NEEDS_COPY
1244
GetStartFc() const1245 WW8_FC WW8_WrFkp::GetStartFc() const
1246 {
1247 // wenn bCombined, dann ist das Array ab pFkp schon Bytemaessig auf LittleEndian
1248 // umgedreht, d.h. zum Herausholen der Anfangs- und Endpositionen muss
1249 // zurueckgedreht werden.
1250 if( bCombined )
1251 return SVBT32ToUInt32( pFkp ); // 0. Element
1252 return ((sal_Int32*)pFkp)[0];
1253 }
1254
GetEndFc() const1255 WW8_FC WW8_WrFkp::GetEndFc() const
1256 {
1257 if( bCombined )
1258 return SVBT32ToUInt32( &(pFkp[nIMax*4]) ); // nIMax-tes SVBT32-Element
1259 return ((sal_Int32*)pFkp)[nIMax];
1260 }
1261
1262 #endif // defined __WW8_NEEDS_COPY
1263
1264
1265
1266 //--------------------------------------------------------------------------
1267 // Methoden fuer Piece-Table-Verwaltung
1268 //--------------------------------------------------------------------------
1269
WW8_WrPct(WW8_FC nfcMin,bool bSaveUniCode)1270 WW8_WrPct::WW8_WrPct(WW8_FC nfcMin, bool bSaveUniCode)
1271 : pPcts(new WW8_WrPcPtrs), nOldFc(nfcMin), bIsUni(bSaveUniCode)
1272 {
1273 AppendPc( nOldFc, bIsUni );
1274 }
1275
~WW8_WrPct()1276 WW8_WrPct::~WW8_WrPct()
1277 {
1278 delete pPcts;
1279 }
1280
1281 // Piece fuellen und neues Piece erzeugen
AppendPc(WW8_FC nStartFc,bool bIsUnicode)1282 void WW8_WrPct::AppendPc(WW8_FC nStartFc, bool bIsUnicode)
1283 {
1284 WW8_CP nStartCp = nStartFc - nOldFc; // Textbeginn abziehen
1285 if ( !nStartCp )
1286 {
1287 if ( 0 != pPcts->Count() )
1288 {
1289 ASSERT( 1 == pPcts->Count(), "Leeres Piece !!");
1290 pPcts->DeleteAndDestroy( pPcts->Count() - 1 , 1);
1291 }
1292 }
1293
1294 nOldFc = nStartFc; // StartFc als alten merken
1295
1296 if( bIsUni )
1297 nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
1298
1299
1300 if ( !bIsUnicode )
1301 {
1302 nStartFc <<= 1; // Adresse * 2
1303 nStartFc |= 0x40000000; // Vorletztes Bit setzen fuer !Unicode
1304 }
1305
1306 if( pPcts->Count() )
1307 nStartCp += pPcts->GetObject( pPcts->Count()- 1 )->GetStartCp();
1308
1309 WW8_WrPcPtr pPc = new WW8_WrPc( nStartFc, nStartCp );
1310 pPcts->Insert( pPc, pPcts->Count() );
1311
1312 bIsUni = bIsUnicode;
1313 }
1314
1315
WritePc(WW8Export & rWrt)1316 void WW8_WrPct::WritePc( WW8Export& rWrt )
1317 {
1318 sal_uLong nPctStart;
1319 sal_uLong nOldPos, nEndPos;
1320 sal_uInt16 i;
1321
1322 nPctStart = rWrt.pTableStrm->Tell(); // Beginn Piece-Table
1323 *rWrt.pTableStrm << ( char )0x02; // Statusbyte PCT
1324 nOldPos = nPctStart + 1; // Position merken
1325 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); // Laenge folgt
1326 for( i = 0; i < pPcts->Count(); ++i ) // Bereiche
1327 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
1328 pPcts->GetObject( i )->GetStartCp() );
1329
1330
1331 // die letzte Pos noch errechnen
1332 sal_uLong nStartCp = rWrt.pFib->fcMac - nOldFc;
1333 if( bIsUni )
1334 nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
1335 nStartCp += pPcts->GetObject( i-1 )->GetStartCp();
1336 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nStartCp );
1337
1338 // Pieceverweise
1339 for ( i = 0; i < pPcts->Count(); ++i )
1340 {
1341 WW8_WrPcPtr pPc = pPcts->GetObject( i );
1342
1343 SwWW8Writer::WriteShort( *rWrt.pTableStrm, pPc->GetStatus());
1344 SwWW8Writer::WriteLong( *rWrt.pTableStrm, pPc->GetStartFc());
1345 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0); // PRM=0
1346 }
1347
1348 // Eintraege im FIB
1349 rWrt.pFib->fcClx = nPctStart;
1350 nEndPos = rWrt.pTableStrm->Tell();
1351 rWrt.pFib->lcbClx = nEndPos - nPctStart;
1352
1353 // und noch die Laenge eintragen
1354 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nOldPos,
1355 nEndPos - nPctStart-5 );
1356
1357 }
1358
SetParaBreak()1359 void WW8_WrPct::SetParaBreak()
1360 {
1361 ASSERT( pPcts->Count(),"SetParaBreak : aPcts.Count = 0" );
1362 pPcts->GetObject( pPcts->Count() - 1)->SetStatus();
1363 }
1364
Fc2Cp(sal_uLong nFc) const1365 WW8_CP WW8_WrPct::Fc2Cp( sal_uLong nFc ) const
1366 {
1367 ASSERT( nFc >= (sal_uLong)nOldFc, "FilePos liegt vorm letzten Piece" );
1368 ASSERT( pPcts->Count(), "Fc2Cp noch kein Piece vorhanden" );
1369
1370 nFc -= nOldFc;
1371 if( bIsUni )
1372 nFc /= 2;
1373 return nFc + pPcts->GetObject( pPcts->Count() - 1 )->GetStartCp();
1374 }
1375
AppendBookmarks(const SwTxtNode & rNd,xub_StrLen nAktPos,xub_StrLen nLen)1376 void WW8Export::AppendBookmarks( const SwTxtNode& rNd,
1377 xub_StrLen nAktPos, xub_StrLen nLen )
1378 {
1379 SvPtrarr aArr( 8, 8 );
1380 sal_uInt16 nCntnt;
1381 xub_StrLen nAktEnd = nAktPos + nLen;
1382 if( GetWriter().GetBookmarks( rNd, nAktPos, nAktEnd, aArr ))
1383 {
1384 sal_uLong nNd = rNd.GetIndex(), nSttCP = Fc2Cp( Strm().Tell() );
1385 for( sal_uInt16 n = 0; n < aArr.Count(); ++n )
1386 {
1387 ::sw::mark::IMark& rBkmk = *(::sw::mark::IMark*)aArr[ n ];
1388 if(dynamic_cast< ::sw::mark::IFieldmark *>(&rBkmk))
1389 continue;
1390
1391 const SwPosition* pPos = &rBkmk.GetMarkPos();
1392 const SwPosition* pOPos = 0;
1393 if(rBkmk.IsExpanded())
1394 pOPos = &rBkmk.GetOtherMarkPos();
1395 if( pOPos && pOPos->nNode == pPos->nNode &&
1396 pOPos->nContent < pPos->nContent )
1397 {
1398 pPos = pOPos;
1399 pOPos = &rBkmk.GetMarkPos();
1400 }
1401
1402 if( !pOPos || ( nNd == pPos->nNode.GetIndex() &&
1403 ( nCntnt = pPos->nContent.GetIndex() ) >= nAktPos &&
1404 nCntnt < nAktEnd ) )
1405 {
1406 sal_uLong nCp = nSttCP + pPos->nContent.GetIndex() - nAktPos;
1407 pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
1408 }
1409 if( pOPos && nNd == pOPos->nNode.GetIndex() &&
1410 ( nCntnt = pOPos->nContent.GetIndex() ) >= nAktPos &&
1411 nCntnt < nAktEnd )
1412 {
1413 sal_uLong nCp = nSttCP + pOPos->nContent.GetIndex() - nAktPos;
1414 pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
1415 }
1416 }
1417 }
1418 }
1419
MoveFieldMarks(sal_uLong nFrom,sal_uLong nTo)1420 void WW8Export::MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo)
1421 {
1422 pBkmks->MoveFieldMarks(nFrom, nTo);
1423 }
1424
AppendBookmark(const rtl::OUString & rName,bool bSkip)1425 void WW8Export::AppendBookmark( const rtl::OUString& rName, bool bSkip )
1426 {
1427 sal_uLong nSttCP = Fc2Cp( Strm().Tell() ) + ( bSkip? 1: 0 );
1428 pBkmks->Append( nSttCP, rName );
1429 }
1430
1431 //For i120928,collect all the graphics of bullets applied to paragraphs
CollectGrfsOfBullets() const1432 int WW8Export::CollectGrfsOfBullets() const
1433 {
1434 m_vecBulletPic.clear();
1435
1436 if ( pDoc )
1437 {
1438 sal_uInt16 nCountRule = pDoc->GetNumRuleTbl().Count();
1439 for (sal_uInt16 n = 0; n < nCountRule; ++n)
1440 {
1441 const SwNumRule &rRule = *(pDoc->GetNumRuleTbl().GetObject(n));
1442 sal_uInt16 nLevels = rRule.IsContinusNum() ? 1 : 9;
1443 for (sal_uInt16 nLvl = 0; nLvl < nLevels; ++nLvl)
1444 {
1445 const SwNumFmt &rFmt = rRule.Get(nLvl);
1446 if (SVX_NUM_BITMAP != rFmt.GetNumberingType())
1447 {
1448 continue;
1449 }
1450 const Graphic *pGrf = rFmt.GetBrush()? rFmt.GetBrush()->GetGraphic():0;
1451 if ( pGrf )
1452 {
1453 bool bHas = false;
1454 for (sal_uInt16 i = 0; i < m_vecBulletPic.size(); ++i)
1455 {
1456 if (m_vecBulletPic[i]->GetChecksum() == pGrf->GetChecksum())
1457 {
1458 bHas = true;
1459 break;
1460 }
1461 }
1462 if (!bHas)
1463 {
1464 m_vecBulletPic.push_back(pGrf);
1465 }
1466 }
1467 }
1468 }
1469 }
1470
1471 return m_vecBulletPic.size();
1472 }
1473 //Export Graphic of Bullets
ExportGrfBullet(const SwTxtNode & rNd)1474 void WW8Export::ExportGrfBullet(const SwTxtNode& rNd)
1475 {
1476 int nCount = CollectGrfsOfBullets();
1477 if (nCount > 0)
1478 {
1479 SwPosition aPos(rNd);
1480 String aPicBullets = String::CreateFromAscii("_PictureBullets");
1481 AppendBookmark(aPicBullets);
1482 for (int i = 0; i < nCount; i++)
1483 {
1484 sw::Frame aFrame(*(m_vecBulletPic[i]), aPos);
1485 OutGrfBullets(aFrame);
1486 }
1487 AppendBookmark(aPicBullets);
1488 }
1489 }
1490
1491 static sal_uInt8 nAttrMagicIdx = 0;
OutGrfBullets(const sw::Frame & rFrame)1492 void WW8Export::OutGrfBullets(const sw::Frame & rFrame)
1493 {
1494 if ( !pGrf || !pChpPlc || !pO )
1495 return;
1496
1497 pGrf->Insert(rFrame);
1498 pChpPlc->AppendFkpEntry( Strm().Tell(), pO->Count(), pO->GetData() );
1499 pO->Remove( 0, pO->Count() );
1500 //if links...
1501 WriteChar( (char)1 );
1502
1503 sal_uInt8 aArr[ 22 ];
1504 sal_uInt8* pArr = aArr;
1505
1506 // sprmCFSpec
1507 if( bWrtWW8 )
1508 Set_UInt16( pArr, 0x855 );
1509 else
1510 Set_UInt8( pArr, 117 );
1511 Set_UInt8( pArr, 1 );
1512
1513 Set_UInt16( pArr, 0x083c );
1514 Set_UInt8( pArr, 0x81 );
1515
1516 // sprmCPicLocation
1517 if( bWrtWW8 )
1518 Set_UInt16( pArr, 0x6a03 );
1519 else
1520 {
1521 Set_UInt8( pArr, 68 );
1522 Set_UInt8( pArr, 4 );
1523 }
1524 Set_UInt32( pArr, GRF_MAGIC_321 );
1525
1526 //extern nAttrMagicIdx;
1527 --pArr;
1528 Set_UInt8( pArr, nAttrMagicIdx++ );
1529 pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
1530 }
1531 //Achieve the index position
GetGrfIndex(const SvxBrushItem & rBrush)1532 int WW8Export::GetGrfIndex(const SvxBrushItem& rBrush)
1533 {
1534 int nIndex = -1;
1535 if ( rBrush.GetGraphic() )
1536 {
1537 for (sal_uInt16 i = 0; i < m_vecBulletPic.size(); ++i)
1538 {
1539 if (m_vecBulletPic[i]->GetChecksum() == rBrush.GetGraphic()->GetChecksum())
1540 {
1541 nIndex = i;
1542 break;
1543 }
1544 }
1545 }
1546
1547 return nIndex;
1548 }
1549
AppendWordBookmark(const String & rName)1550 void MSWordExportBase::AppendWordBookmark( const String& rName )
1551 {
1552 AppendBookmark( BookmarkToWord( rName ) );
1553 }
1554
1555
1556 //--------------------------------------------------------------------------
1557 /* */
1558
Write(Writer & rWrt)1559 void WW8_WrtRedlineAuthor::Write( Writer& rWrt )
1560 {
1561 WW8Export & rWW8Wrt = *(((SwWW8Writer&)rWrt).m_pExport);
1562 rWW8Wrt.WriteAsStringTable(maAuthors, rWW8Wrt.pFib->fcSttbfRMark,
1563 rWW8Wrt.pFib->lcbSttbfRMark, rWW8Wrt.bWrtWW8 ? 0 : 2);
1564 }
1565
AddRedlineAuthor(sal_uInt16 nId)1566 sal_uInt16 WW8Export::AddRedlineAuthor( sal_uInt16 nId )
1567 {
1568 if( !pRedlAuthors )
1569 {
1570 pRedlAuthors = new WW8_WrtRedlineAuthor;
1571 pRedlAuthors->AddName(CREATE_CONST_ASC("Unknown"));
1572 }
1573 return pRedlAuthors->AddName( SW_MOD()->GetRedlineAuthor( nId ) );
1574 }
1575
1576 //--------------------------------------------------------------------------
1577 /* */
1578
WriteAsStringTable(const std::vector<String> & rStrings,sal_Int32 & rfcSttbf,sal_Int32 & rlcbSttbf,sal_uInt16 nExtraLen)1579 void WW8Export::WriteAsStringTable(const std::vector<String>& rStrings,
1580 sal_Int32& rfcSttbf, sal_Int32& rlcbSttbf, sal_uInt16 nExtraLen)
1581 {
1582 sal_uInt16 n, nCount = static_cast< sal_uInt16 >(rStrings.size());
1583 if( nCount )
1584 {
1585 // we have some Redlines found in the document -> the
1586 // Author Name Stringtable
1587 SvStream& rStrm = bWrtWW8 ? *pTableStrm : Strm();
1588 rfcSttbf = rStrm.Tell();
1589 if( bWrtWW8 )
1590 {
1591 SwWW8Writer::WriteShort( rStrm, -1 );
1592 SwWW8Writer::WriteLong( rStrm, nCount );
1593 for( n = 0; n < nCount; ++n )
1594 {
1595 const String& rNm = rStrings[n];
1596 SwWW8Writer::WriteShort( rStrm, rNm.Len() );
1597 SwWW8Writer::WriteString16(rStrm, rNm, false);
1598 if( nExtraLen )
1599 SwWW8Writer::FillCount(rStrm, nExtraLen);
1600 }
1601 }
1602 else
1603 {
1604 SwWW8Writer::WriteShort( rStrm, 0 );
1605 for( n = 0; n < nCount; ++n )
1606 {
1607 const String aNm(rStrings[n].Copy(0, 255));
1608 rStrm << (sal_uInt8)aNm.Len();
1609 SwWW8Writer::WriteString8(rStrm, aNm, false,
1610 RTL_TEXTENCODING_MS_1252);
1611 if (nExtraLen)
1612 SwWW8Writer::FillCount(rStrm, nExtraLen);
1613 }
1614 }
1615 rlcbSttbf = rStrm.Tell() - rfcSttbf;
1616 if( !bWrtWW8 )
1617 SwWW8Writer::WriteShort( rStrm, rfcSttbf, (sal_uInt16)rlcbSttbf );
1618 }
1619 }
1620
1621 // WriteShort() traegt an FilePos nPos den Wert nVal ein und seekt auf die
1622 // alte FilePos zurueck. Benutzt zum Nachtragen von Laengen.
WriteShort(SvStream & rStrm,sal_uLong nPos,sal_Int16 nVal)1623 void SwWW8Writer::WriteShort( SvStream& rStrm, sal_uLong nPos, sal_Int16 nVal )
1624 {
1625 sal_uLong nOldPos = rStrm.Tell(); // Pos merken
1626 rStrm.Seek( nPos );
1627 SwWW8Writer::WriteShort( rStrm, nVal );
1628 rStrm.Seek( nOldPos );
1629 }
1630
WriteLong(SvStream & rStrm,sal_uLong nPos,sal_Int32 nVal)1631 void SwWW8Writer::WriteLong( SvStream& rStrm, sal_uLong nPos, sal_Int32 nVal )
1632 {
1633 sal_uLong nOldPos = rStrm.Tell(); // Pos merken
1634 rStrm.Seek( nPos );
1635 SwWW8Writer::WriteLong( rStrm, nVal );
1636 rStrm.Seek( nOldPos );
1637 }
1638
InsUInt16(ww::bytes & rO,sal_uInt16 n)1639 void SwWW8Writer::InsUInt16(ww::bytes &rO, sal_uInt16 n)
1640 {
1641 SVBT16 nL;
1642 ShortToSVBT16( n, nL );
1643 rO.push_back(nL[0]);
1644 rO.push_back(nL[1]);
1645 }
1646
InsUInt32(ww::bytes & rO,sal_uInt32 n)1647 void SwWW8Writer::InsUInt32(ww::bytes &rO, sal_uInt32 n)
1648 {
1649 SVBT32 nL;
1650 UInt32ToSVBT32( n, nL );
1651 rO.push_back(nL[0]);
1652 rO.push_back(nL[1]);
1653 rO.push_back(nL[2]);
1654 rO.push_back(nL[3]);
1655 }
1656
InsAsString16(ww::bytes & rO,const String & rStr)1657 void SwWW8Writer::InsAsString16(ww::bytes &rO, const String& rStr)
1658 {
1659 const sal_Unicode* pStr = rStr.GetBuffer();
1660 for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
1661 SwWW8Writer::InsUInt16( rO, *pStr );
1662 }
1663
InsAsString8(ww::bytes & rO,const String & rStr,rtl_TextEncoding eCodeSet)1664 void SwWW8Writer::InsAsString8(ww::bytes &rO, const String& rStr,
1665 rtl_TextEncoding eCodeSet)
1666 {
1667 ByteString sTmp(rStr, eCodeSet);
1668 const sal_Char *pStart = sTmp.GetBuffer();
1669 const sal_Char *pEnd = pStart + sTmp.Len();
1670 rO.reserve(rO.size() + sTmp.Len());
1671
1672 std::copy(pStart, pEnd, std::inserter(rO, rO.end()));
1673 }
1674
1675 #ifdef __WW8_NEEDS_COPY
1676
InsUInt16(WW8Bytes & rO,sal_uInt16 n)1677 void SwWW8Writer::InsUInt16( WW8Bytes& rO, sal_uInt16 n )
1678 {
1679 SVBT16 nL;
1680 ShortToSVBT16( n, nL );
1681 rO.Insert( nL, 2, rO.Count() );
1682 }
InsUInt32(WW8Bytes & rO,sal_uInt32 n)1683 void SwWW8Writer::InsUInt32( WW8Bytes& rO, sal_uInt32 n )
1684 {
1685 SVBT32 nL;
1686 UInt32ToSVBT32( n, nL );
1687 rO.Insert( nL, 4, rO.Count() );
1688 }
1689
1690 #else
1691
InsUInt16(WW8Bytes & rO,sal_uInt16 n)1692 void SwWW8Writer::InsUInt16( WW8Bytes& rO, sal_uInt16 n )
1693 {
1694 rO.Insert( (sal_uInt8*)&n, 2, rO.Count() );
1695 }
InsUInt32(WW8Bytes & rO,sal_uInt32 n)1696 void SwWW8Writer::InsUInt32( WW8Bytes& rO, sal_uInt32 n )
1697 {
1698 rO.Insert( (sal_uInt8*)&n, 4, rO.Count() );
1699 }
1700
1701 #endif // defined __WW8_NEEDS_COPY
1702
InsAsString16(WW8Bytes & rO,const String & rStr)1703 void SwWW8Writer::InsAsString16( WW8Bytes& rO, const String& rStr )
1704 {
1705 const sal_Unicode* pStr = rStr.GetBuffer();
1706 for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
1707 SwWW8Writer::InsUInt16( rO, *pStr );
1708 }
1709
InsAsString8(WW8Bytes & rO,const String & rStr,rtl_TextEncoding eCodeSet)1710 void SwWW8Writer::InsAsString8( WW8Bytes& rO, const String& rStr,
1711 rtl_TextEncoding eCodeSet )
1712 {
1713 ByteString sTmp( rStr, eCodeSet );
1714 rO.Insert( (sal_uInt8*)sTmp.GetBuffer(), sTmp.Len(), rO.Count() );
1715 }
1716
WriteString16(SvStream & rStrm,const String & rStr,bool bAddZero)1717 void SwWW8Writer::WriteString16(SvStream& rStrm, const String& rStr,
1718 bool bAddZero)
1719 {
1720 ww::bytes aBytes;
1721 SwWW8Writer::InsAsString16(aBytes, rStr);
1722 if (bAddZero)
1723 SwWW8Writer::InsUInt16(aBytes, 0);
1724 //vectors are guaranteed to have contiguous memory, so we can do
1725 //this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1726 if (!aBytes.empty())
1727 rStrm.Write(&aBytes[0], aBytes.size());
1728 }
1729
WriteString_xstz(SvStream & rStrm,const String & rStr,bool bAddZero)1730 void SwWW8Writer::WriteString_xstz(SvStream& rStrm, const String& rStr, bool bAddZero)
1731 {
1732 ww::bytes aBytes;
1733 SwWW8Writer::InsUInt16(aBytes, rStr.Len());
1734 SwWW8Writer::InsAsString16(aBytes, rStr);
1735 if (bAddZero)
1736 SwWW8Writer::InsUInt16(aBytes, 0);
1737 rStrm.Write(&aBytes[0], aBytes.size());
1738 }
1739
1740
WriteString8(SvStream & rStrm,const String & rStr,bool bAddZero,rtl_TextEncoding eCodeSet)1741 void SwWW8Writer::WriteString8(SvStream& rStrm, const String& rStr,
1742 bool bAddZero, rtl_TextEncoding eCodeSet)
1743 {
1744 ww::bytes aBytes;
1745 SwWW8Writer::InsAsString8(aBytes, rStr, eCodeSet);
1746 if (bAddZero)
1747 aBytes.push_back(0);
1748 //vectors are guaranteed to have contiguous memory, so we can do
1749 ////this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1750 if (!aBytes.empty())
1751 rStrm.Write(&aBytes[0], aBytes.size());
1752 }
1753
WriteStringAsPara(const String & rTxt,sal_uInt16 nStyleId)1754 void WW8Export::WriteStringAsPara( const String& rTxt, sal_uInt16 nStyleId )
1755 {
1756 if( rTxt.Len() )
1757 OutSwString( rTxt, 0, rTxt.Len(), IsUnicode(), RTL_TEXTENCODING_MS_1252 );
1758 WriteCR(); // CR danach
1759
1760 WW8Bytes aArr( 10, 10 );
1761 SwWW8Writer::InsUInt16( aArr, nStyleId );
1762 if( bOutTable )
1763 { // Tab-Attr
1764 // sprmPFInTable
1765 if( bWrtWW8 )
1766 SwWW8Writer::InsUInt16( aArr, NS_sprm::LN_PFInTable );
1767 else
1768 aArr.Insert( 24, aArr.Count() );
1769 aArr.Insert( 1, aArr.Count() );
1770 }
1771
1772 sal_uLong nPos = Strm().Tell();
1773 pPapPlc->AppendFkpEntry( nPos, aArr.Count(), aArr.GetData() );
1774 pChpPlc->AppendFkpEntry( nPos );
1775 }
1776
WriteSpecialText(sal_uLong nStart,sal_uLong nEnd,sal_uInt8 nTTyp)1777 void MSWordExportBase::WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_uInt8 nTTyp )
1778 {
1779 sal_uInt8 nOldTyp = nTxtTyp;
1780 nTxtTyp = nTTyp;
1781 SwPaM* pOldPam = pCurPam; //!! Einfaches Umsetzen des PaM ohne
1782 SwPaM* pOldEnd = pOrigPam; // Wiederherstellen muesste es auch tun
1783 bool bOldPageDescs = bOutPageDescs;
1784 bOutPageDescs = false;
1785 // bOutKF wird in WriteKF1 gemerkt / gesetzt
1786 pCurPam = Writer::NewSwPaM( *pDoc, nStart, nEnd );
1787
1788 // Tabelle in Sonderbereichen erkennen
1789 if ( ( nStart != pCurPam->GetMark()->nNode.GetIndex() ) &&
1790 pDoc->GetNodes()[ nStart ]->IsTableNode() )
1791 {
1792 pCurPam->GetMark()->nNode = nStart;
1793 }
1794
1795 pOrigPam = pCurPam;
1796 pCurPam->Exchange();
1797
1798 WriteText();
1799
1800 bOutPageDescs = bOldPageDescs;
1801 delete pCurPam; // Pam wieder loeschen
1802 pCurPam = pOldPam;
1803 pOrigPam = pOldEnd;
1804 nTxtTyp = nOldTyp;
1805 }
1806
OutSwString(const String & rStr,xub_StrLen nStt,xub_StrLen nLen,bool bUnicode,rtl_TextEncoding eChrSet)1807 void WW8Export::OutSwString(const String& rStr, xub_StrLen nStt,
1808 xub_StrLen nLen, bool bUnicode, rtl_TextEncoding eChrSet)
1809
1810 {
1811 #ifdef DEBUG
1812 ::std::clog << "<OutSwString>" << ::std::endl;
1813 #endif
1814
1815 if( nLen )
1816 {
1817 if ( bUnicode != pPiece->IsUnicode() )
1818 pPiece->AppendPc ( Strm().Tell(), bUnicode );
1819
1820 if( nStt || nLen != rStr.Len() )
1821 {
1822 String sOut( rStr.Copy( nStt, nLen ) );
1823
1824 #ifdef DEBUG
1825 ::std::clog << ::rtl::OUStringToOString(sOut, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
1826 #endif
1827
1828 if (bUnicode)
1829 SwWW8Writer::WriteString16(Strm(), sOut, false);
1830 else
1831 SwWW8Writer::WriteString8(Strm(), sOut, false, eChrSet);
1832 }
1833 else
1834 {
1835 #ifdef DEBUG
1836 ::std::clog << ::rtl::OUStringToOString(rStr, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
1837 #endif
1838
1839 if (bUnicode)
1840 SwWW8Writer::WriteString16(Strm(), rStr, false);
1841 else
1842 SwWW8Writer::WriteString8(Strm(), rStr, false, eChrSet);
1843 }
1844 }
1845
1846 #ifdef DEBUG
1847 ::std::clog << "</OutSwString>" << ::std::endl;
1848 #endif
1849 }
1850
WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1851 void WW8Export::WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
1852 {
1853 if (pTableTextNodeInfoInner.get() != NULL && pTableTextNodeInfoInner->getDepth() == 1 && pTableTextNodeInfoInner->isEndOfCell())
1854 WriteChar('\007');
1855 else
1856 WriteChar( '\015' );
1857
1858 pPiece->SetParaBreak();
1859 }
1860
WriteChar(sal_Unicode c)1861 void WW8Export::WriteChar( sal_Unicode c )
1862 {
1863 if( pPiece->IsUnicode() )
1864 Strm() << c;
1865 else
1866 Strm() << (sal_uInt8)c;
1867 }
1868
SaveData(sal_uLong nStt,sal_uLong nEnd)1869 void MSWordExportBase::SaveData( sal_uLong nStt, sal_uLong nEnd )
1870 {
1871 MSWordSaveData aData;
1872
1873 // WW8Export only stuff - zeroed here not to issue warnings
1874 aData.pOOld = NULL;
1875 aData.mpTableAtOld = NULL;
1876 aData.mnTableStdAtLenOld = 0;
1877
1878 // Common stuff
1879 aData.pOldPam = pCurPam;
1880 aData.pOldEnd = pOrigPam;
1881 aData.pOldFlyFmt = mpParentFrame;
1882 aData.pOldPageDesc = pAktPageDesc;
1883
1884 aData.pOldFlyOffset = pFlyOffset;
1885 aData.eOldAnchorType = eNewAnchorType;
1886
1887 aData.bOldOutTable = bOutTable;
1888 aData.bOldFlyFrmAttrs = bOutFlyFrmAttrs;
1889 aData.bOldStartTOX = bStartTOX;
1890 aData.bOldInWriteTOX = bInWriteTOX;
1891
1892 pCurPam = Writer::NewSwPaM( *pDoc, nStt, nEnd );
1893
1894 // Recognize tables in special cases
1895 if ( nStt != pCurPam->GetMark()->nNode.GetIndex() &&
1896 pDoc->GetNodes()[ nStt ]->IsTableNode() )
1897 {
1898 pCurPam->GetMark()->nNode = nStt;
1899 }
1900
1901 pOrigPam = pCurPam;
1902 pCurPam->Exchange();
1903
1904 bOutTable = false;
1905 // Caution: bIsInTable should not be set here
1906 bOutFlyFrmAttrs = false;
1907 // pAttrSet = 0;
1908 bStartTOX = false;
1909 bInWriteTOX = false;
1910
1911 maSaveData.push( aData );
1912 }
1913
RestoreData()1914 void MSWordExportBase::RestoreData()
1915 {
1916 MSWordSaveData &rData = maSaveData.top();
1917
1918 delete pCurPam;
1919 pCurPam = rData.pOldPam;
1920 pOrigPam = rData.pOldEnd;
1921
1922 bOutTable = rData.bOldOutTable;
1923 bOutFlyFrmAttrs = rData.bOldFlyFrmAttrs;
1924 bStartTOX = rData.bOldStartTOX;
1925 bInWriteTOX = rData.bOldInWriteTOX;
1926
1927 mpParentFrame = rData.pOldFlyFmt;
1928 pAktPageDesc = rData.pOldPageDesc;
1929
1930 eNewAnchorType = rData.eOldAnchorType;
1931 pFlyOffset = rData.pOldFlyOffset;
1932
1933 maSaveData.pop();
1934 }
1935
SaveData(sal_uLong nStt,sal_uLong nEnd)1936 void WW8Export::SaveData( sal_uLong nStt, sal_uLong nEnd )
1937 {
1938 MSWordExportBase::SaveData( nStt, nEnd );
1939
1940 MSWordSaveData &rData = maSaveData.top();
1941
1942 if ( pO->Count() )
1943 {
1944 rData.pOOld = pO;
1945 pO = new WW8Bytes( 128, 128 );
1946 }
1947 else
1948 rData.pOOld = 0; // reuse pO
1949
1950 rData.mpTableAtOld = mpTableAt;
1951 mpTableAt = NULL;
1952 rData.mnTableStdAtLenOld = mnTableStdAtLen;
1953 mnTableStdAtLen = 0;
1954
1955 rData.bOldWriteAll = GetWriter().bWriteAll;
1956 GetWriter().bWriteAll = true;
1957 }
1958
RestoreData()1959 void WW8Export::RestoreData()
1960 {
1961 MSWordSaveData &rData = maSaveData.top();
1962
1963 GetWriter().bWriteAll = rData.bOldWriteAll;
1964
1965 ASSERT( !pO->Count(), "pO is not empty in WW8Export::RestoreData()" );
1966 if ( rData.pOOld )
1967 {
1968 delete pO;
1969 pO = rData.pOOld;
1970 }
1971
1972 ASSERT( !mpTableAt || !mpTableAt->Count(), "mpTableAt is not empty in WW8Export::RestoreData()" );
1973 if ( mpTableAt )
1974 delete mpTableAt;
1975 mpTableAt = rData.mpTableAtOld;
1976 mnTableStdAtLen = rData.mnTableStdAtLenOld;
1977
1978 MSWordExportBase::RestoreData();
1979 }
1980
TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1981 void WW8AttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1982 {
1983 sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
1984
1985 if ( nDepth > 0 )
1986 {
1987 /* Cell */
1988 m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
1989 m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
1990 m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
1991 m_rWW8Export.InsUInt32( nDepth );
1992
1993 if ( nDepth > 1 && pTableTextNodeInfoInner->isEndOfCell() )
1994 {
1995 m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
1996 m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
1997 }
1998 }
1999 }
2000
TableInfoRow(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2001 void WW8AttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2002 {
2003 sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
2004
2005 if ( nDepth > 0 )
2006 {
2007 /* Row */
2008 if ( pTableTextNodeInfoInner->isEndOfLine() )
2009 {
2010 m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
2011 m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
2012
2013 if ( nDepth == 1 )
2014 {
2015 m_rWW8Export.InsUInt16( NS_sprm::LN_PFTtp );
2016 m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
2017 }
2018
2019 m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
2020 m_rWW8Export.InsUInt32( nDepth );
2021
2022 if ( nDepth > 1 )
2023 {
2024 m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
2025 m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
2026 m_rWW8Export.InsUInt16( NS_sprm::LN_PRow );
2027 m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
2028 }
2029
2030 TableDefinition( pTableTextNodeInfoInner );
2031 TableHeight( pTableTextNodeInfoInner );
2032 TableBackgrounds( pTableTextNodeInfoInner );
2033 TableDefaultBorders( pTableTextNodeInfoInner );
2034 TableCanSplit( pTableTextNodeInfoInner );
2035 TableBidi( pTableTextNodeInfoInner );
2036 TableVerticalCell( pTableTextNodeInfoInner );
2037 TableOrientation( pTableTextNodeInfoInner );
2038 TableSpacing( pTableTextNodeInfoInner );
2039 }
2040 }
2041 }
2042
lcl_TCFlags(SwDoc & rDoc,const SwTableBox * pBox,const sal_Int32 nRowSpan)2043 static sal_uInt16 lcl_TCFlags(SwDoc &rDoc, const SwTableBox * pBox, const sal_Int32 nRowSpan)
2044 {
2045 sal_uInt16 nFlags = 0;
2046
2047 if (nRowSpan > 1)
2048 nFlags |= (3 << 5);
2049 else if (nRowSpan < 0)
2050 nFlags |= (1 << 5);
2051
2052 if (pBox != NULL)
2053 {
2054 const SwFrmFmt * pFmt = pBox->GetFrmFmt();
2055 switch (pFmt->GetVertOrient().GetVertOrient())
2056 {
2057 case text::VertOrientation::CENTER:
2058 nFlags |= (1 << 7);
2059 break;
2060 case text::VertOrientation::BOTTOM:
2061 nFlags |= (2 << 7);
2062 break;
2063 default:
2064 break;
2065 }
2066 const SwStartNode * pSttNd = pBox->GetSttNd();
2067 if(pSttNd)
2068 {
2069 SwNodeIndex aIdx( *pSttNd );
2070 const SwCntntNode * pCNd = pSttNd->GetNodes().GoNext( &aIdx );
2071 if( pCNd && pCNd->IsTxtNode())
2072 {
2073 SfxItemSet aCoreSet(rDoc.GetAttrPool(), RES_CHRATR_ROTATE, RES_CHRATR_ROTATE);
2074 ((SwTxtNode*)pCNd)->GetAttr( aCoreSet, 0, ((SwTxtNode*)pCNd)->GetTxt().Len());
2075 const SvxCharRotateItem * pRotate = NULL;
2076 const SfxPoolItem * pRotItem;
2077 if ( SFX_ITEM_SET == aCoreSet.GetItemState(RES_CHRATR_ROTATE, sal_True, &pRotItem))
2078 {
2079 pRotate = (SvxCharRotateItem*)pRotItem;
2080 if(pRotate && pRotate->GetValue() == 900)
2081 {
2082 nFlags = nFlags | 0x0004 | 0x0008;
2083 }
2084 else if(pRotate && pRotate->GetValue() == 2700 )
2085 {
2086 nFlags = nFlags | 0x0004 | 0x0010;
2087 }
2088 }
2089 }
2090 }
2091 }
2092
2093 return nFlags;
2094 }
2095
TableVerticalCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2096 void WW8AttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2097 {
2098 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2099 const SwTableLine * pTabLine = pTabBox->GetUpper();
2100 const SwTableBoxes & rTblBoxes = pTabLine->GetTabBoxes();
2101
2102 const sal_uInt16 nBoxes = rTblBoxes.Count();
2103 for ( sal_uInt16 n = 0; n < nBoxes; n++ )
2104 {
2105 const SwTableBox * pTabBox1 = rTblBoxes[n];
2106 const SwFrmFmt * pFrmFmt = pTabBox1->GetFrmFmt();
2107
2108 if ( FRMDIR_VERT_TOP_RIGHT == m_rWW8Export.TrueFrameDirection( *pFrmFmt ) )
2109 {
2110 m_rWW8Export.InsUInt16( NS_sprm::LN_TTextFlow );
2111 m_rWW8Export.pO->Insert( sal_uInt8(n), m_rWW8Export.pO->Count() ); //start range
2112 m_rWW8Export.pO->Insert( sal_uInt8(n + 1), m_rWW8Export.pO->Count() ); //end range
2113 m_rWW8Export.InsUInt16( 5 ); //Equals vertical writing
2114 }
2115 }
2116 }
2117
TableCanSplit(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2118 void WW8AttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2119 {
2120 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2121 const SwTableLine * pTabLine = pTabBox->GetUpper();
2122 const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
2123
2124 /*
2125 By default the row can be split in word, and now in writer we have a
2126 feature equivalent to this, Word stores 1 for fCantSplit if the row
2127 cannot be split, we set true if we can split it. An example is #i4569#
2128 */
2129
2130 const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit();
2131 sal_uInt8 nCantSplit = (!rSplittable.GetValue()) ? 1 : 0;
2132 if ( m_rWW8Export.bWrtWW8 )
2133 {
2134 m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit );
2135 m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
2136 m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit90 ); // also write fCantSplit90
2137 }
2138 else
2139 {
2140 m_rWW8Export.pO->Insert( 185, m_rWW8Export.pO->Count() );
2141 }
2142 m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
2143 }
2144
TableBidi(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2145 void WW8AttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2146 {
2147 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2148 const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
2149
2150 if ( m_rWW8Export.bWrtWW8 )
2151 {
2152 if ( m_rWW8Export.TrueFrameDirection(*pFrmFmt) == FRMDIR_HORI_RIGHT_TOP )
2153 {
2154 m_rWW8Export.InsUInt16( NS_sprm::LN_TFBiDi );
2155 m_rWW8Export.InsUInt16( 1 );
2156 }
2157 }
2158 }
2159
TableHeight(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2160 void WW8AttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2161 {
2162 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2163 const SwTableLine * pTabLine = pTabBox->GetUpper();
2164 const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
2165
2166 #if 0
2167 const SwTable * pTable = pTableTextNodeInfo->getTable();
2168 bool bNewTableModel = pTable->IsNewModel();
2169 bool bFixRowHeight = false;
2170 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2171 if (! bNewModel)
2172 {
2173 sal_uInt32 nBoxes = rTabBoxes.Count();
2174
2175 for (sal_uInt32 n = 0; n < nBoxes; n++)
2176 {
2177 SwTableBox * pBox1 = rTabBoxes[n];
2178 if (pBox1->getRowspan() != 1)
2179 {
2180 bFixRowHeight = true;
2181 break;
2182 }
2183 }
2184 }
2185 #endif
2186
2187 // Zeilenhoehe ausgeben sprmTDyaRowHeight
2188 long nHeight = 0;
2189 const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
2190 if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
2191 {
2192 if ( ATT_MIN_SIZE == rLSz.GetHeightSizeType() )
2193 nHeight = rLSz.GetHeight();
2194 else
2195 nHeight = -rLSz.GetHeight();
2196 }
2197
2198 if ( nHeight )
2199 {
2200 if ( m_rWW8Export.bWrtWW8 )
2201 m_rWW8Export.InsUInt16( NS_sprm::LN_TDyaRowHeight );
2202 else
2203 m_rWW8Export.pO->Insert( 189, m_rWW8Export.pO->Count() );
2204 m_rWW8Export.InsUInt16( (sal_uInt16)nHeight );
2205 }
2206
2207 }
2208
TableOrientation(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2209 void WW8AttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2210 {
2211 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2212
2213 const SwFrmFmt *pFmt = pTable->GetFrmFmt();
2214 ASSERT(pFmt,"Impossible");
2215 if (!pFmt)
2216 return;
2217
2218 const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
2219 const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
2220
2221 if (
2222 (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2223 text::RelOrientation::FRAME == rHori.GetRelationOrient())
2224 &&
2225 (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2226 text::RelOrientation::FRAME == rVert.GetRelationOrient())
2227 )
2228 {
2229 sal_Int16 eHOri = rHori.GetHoriOrient();
2230 switch (eHOri)
2231 {
2232 case text::HoriOrientation::CENTER:
2233 case text::HoriOrientation::RIGHT:
2234 if ( m_rWW8Export.bWrtWW8 )
2235 m_rWW8Export.InsUInt16( NS_sprm::LN_TJc );
2236 else
2237 m_rWW8Export.pO->Insert( 182, m_rWW8Export.pO->Count() );
2238 m_rWW8Export.InsUInt16( text::HoriOrientation::RIGHT == eHOri ? 2 : 1 );
2239 break;
2240 default:
2241 break;
2242 }
2243 }
2244 }
2245
TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2246 void WW8AttributeOutput::TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
2247 {
2248 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2249 const SwTableFmt * pTableFmt = pTable->GetTableFmt();
2250
2251 if (pTableFmt != NULL)
2252 {
2253 const SvxULSpaceItem & rUL = pTableFmt->GetULSpace();
2254
2255 if (rUL.GetUpper() > 0)
2256 {
2257 sal_uInt8 nPadding = 2;
2258 sal_uInt8 nPcVert = 0;
2259 sal_uInt8 nPcHorz = 0;
2260
2261 sal_uInt8 nTPc = (nPadding << 4) | (nPcVert << 2) | nPcHorz;
2262
2263 m_rWW8Export.InsUInt16(NS_sprm::LN_TPc);
2264 m_rWW8Export.pO->Insert( nTPc, m_rWW8Export.pO->Count() );
2265
2266 m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaAbs);
2267 m_rWW8Export.InsUInt16(rUL.GetUpper());
2268
2269 m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaFromText);
2270 m_rWW8Export.InsUInt16(rUL.GetUpper());
2271 }
2272
2273 if (rUL.GetLower() > 0)
2274 {
2275 m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaFromTextBottom);
2276 m_rWW8Export.InsUInt16(rUL.GetLower());
2277 }
2278 }
2279 }
2280
TableDefinition(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2281 void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2282 {
2283 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2284
2285 if ( pTable->GetRowsToRepeat() > pTableTextNodeInfoInner->getRow() )
2286 {
2287 if( m_rWW8Export.bWrtWW8 )
2288 m_rWW8Export.InsUInt16( NS_sprm::LN_TTableHeader );
2289 else
2290 m_rWW8Export.pO->Insert( 186, m_rWW8Export.pO->Count() );
2291 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
2292 }
2293
2294 ww8::TableBoxVectorPtr pTableBoxes = pTableTextNodeInfoInner->getTableBoxesOfRow();
2295 // number of cell written
2296 const sal_uInt16 nBoxes =
2297 pTableBoxes->size() > ww8::MAXTABLECELLS
2298 ? ww8::MAXTABLECELLS
2299 : static_cast< sal_uInt16 >(pTableBoxes->size());
2300
2301 // sprm header
2302 m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTable );
2303 const sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
2304 m_rWW8Export.InsUInt16( nSprmSize ); // length
2305
2306 // number of boxes
2307 m_rWW8Export.pO->Insert( static_cast<sal_uInt8>(nBoxes), m_rWW8Export.pO->Count() );
2308
2309 /* cellxs */
2310 /*
2311 ALWAYS relative when text::HoriOrientation::NONE (nPageSize + ( nPageSize / 10 )) < nTblSz,
2312 in that case the cell width's and table width's are not real. The table
2313 width is maxed and cells relative, so we need the frame (generally page)
2314 width that the table is in to work out the true widths.
2315 */
2316 //const bool bNewTableModel = pTbl->IsNewModel();
2317 const SwFrmFmt *pFmt = pTable->GetFrmFmt();
2318 ASSERT(pFmt,"Impossible");
2319 if (!pFmt)
2320 return;
2321
2322 const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
2323 const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
2324
2325 sal_uInt16 nTblOffset = 0;
2326
2327 if (
2328 (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2329 text::RelOrientation::FRAME == rHori.GetRelationOrient())
2330 &&
2331 (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2332 text::RelOrientation::FRAME == rVert.GetRelationOrient())
2333 )
2334 {
2335 sal_Int16 eHOri = rHori.GetHoriOrient();
2336 switch ( eHOri )
2337 {
2338 case text::HoriOrientation::CENTER:
2339 case text::HoriOrientation::RIGHT:
2340 break;
2341
2342 default:
2343 nTblOffset = static_cast< sal_uInt16 >(rHori.GetPos());
2344 const SvxLRSpaceItem& rLRSp = pFmt->GetLRSpace();
2345 nTblOffset += static_cast< sal_uInt16 >(rLRSp.GetLeft());
2346 break;
2347 }
2348 }
2349
2350 m_rWW8Export.InsUInt16( nTblOffset );
2351
2352 ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
2353 for ( ww8::GridCols::const_iterator it = pGridCols->begin(),
2354 end = pGridCols->end(); it != end; ++it )
2355 {
2356 m_rWW8Export.InsUInt16( static_cast<sal_uInt16>( *it ) + nTblOffset );
2357 }
2358
2359 /* TCs */
2360 ww8::RowSpansPtr pRowSpans = pTableTextNodeInfoInner->getRowSpansOfRow();
2361 ww8::RowSpans::const_iterator aItRowSpans = pRowSpans->begin();
2362 ww8::TableBoxVector::const_iterator aIt;
2363 ww8::TableBoxVector::const_iterator aItEnd = pTableBoxes->end();
2364
2365 #ifdef DEBUG
2366 size_t nRowSpans = pRowSpans->size();
2367 size_t nTableBoxes = pTableBoxes->size();
2368 (void) nRowSpans;
2369 (void) nTableBoxes;
2370 #endif
2371
2372 for( aIt = pTableBoxes->begin(); aIt != aItEnd; ++aIt, ++aItRowSpans)
2373 {
2374 #ifdef DEBUG
2375 sal_uInt16 npOCount = m_rWW8Export.pO->Count();
2376 #endif
2377
2378 const SwTableBox * pTabBox1 = *aIt;
2379 const SwFrmFmt * pBoxFmt = NULL;
2380 if (pTabBox1 != NULL)
2381 pBoxFmt = pTabBox1->GetFrmFmt();
2382
2383 if ( m_rWW8Export.bWrtWW8 )
2384 {
2385 sal_uInt16 nFlags =
2386 lcl_TCFlags(*m_rWW8Export.pDoc, pTabBox1, *aItRowSpans);
2387 m_rWW8Export.InsUInt16( nFlags );
2388 }
2389
2390 static sal_uInt8 aNullBytes[] = { 0x0, 0x0 };
2391
2392 m_rWW8Export.pO->Insert( aNullBytes, 2, m_rWW8Export.pO->Count() ); // dummy
2393 if (pBoxFmt != NULL)
2394 {
2395 const SvxBoxItem & rBoxItem = pBoxFmt->GetBox();
2396
2397 m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, &rBoxItem ); // 8/16 Byte
2398 }
2399 else
2400 m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, NULL); // 8/16 Byte
2401
2402 #ifdef DEBUG
2403 ::std::clog << "<tclength>" << m_rWW8Export.pO->Count() - npOCount << "</tclength>"
2404 << ::std::endl;
2405 #endif
2406 }
2407 }
2408
GetGridCols(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2409 ww8::GridColsPtr AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2410 {
2411 return pTableTextNodeInfoInner->getGridColsOfRow(*this);
2412 }
2413
GetTablePageSize(ww8::WW8TableNodeInfoInner * pTableTextNodeInfoInner,sal_uInt32 & rPageSize,bool & rRelBoxSize)2414 void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner * pTableTextNodeInfoInner, sal_uInt32& rPageSize, bool& rRelBoxSize )
2415 {
2416 sal_uInt32 nPageSize = 0;
2417
2418 const SwNode *pTxtNd = pTableTextNodeInfoInner->getNode( );
2419 const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
2420
2421 const SwFrmFmt *pFmt = pTable->GetFrmFmt();
2422 ASSERT(pFmt,"Impossible");
2423 if (!pFmt)
2424 return;
2425
2426 const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
2427 int nWidthPercent = rSize.GetWidthPercent();
2428 bool bManualAligned = pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::NONE;
2429 if ( (pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::FULL) || bManualAligned )
2430 nWidthPercent = 100;
2431 bool bRelBoxSize = nWidthPercent != 0;
2432 unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
2433 if (nTblSz > USHRT_MAX/2 && !bRelBoxSize)
2434 {
2435 ASSERT(bRelBoxSize, "huge table width but not relative, suspicious");
2436 bRelBoxSize = true;
2437 }
2438
2439 if ( bRelBoxSize )
2440 {
2441 Point aPt;
2442 SwRect aRect( pFmt->FindLayoutRect( false, &aPt ) );
2443 if ( aRect.IsEmpty() )
2444 {
2445 // dann besorge mal die Seitenbreite ohne Raender !!
2446 const SwFrmFmt* pParentFmt =
2447 GetExport().mpParentFrame ?
2448 &(GetExport().mpParentFrame->GetFrmFmt()) :
2449 const_cast<const SwDoc *>(GetExport().pDoc)->GetPageDesc(0).GetPageFmtOfNode(*pTxtNd, false);
2450 aRect = pParentFmt->FindLayoutRect(true);
2451 if ( 0 == ( nPageSize = aRect.Width() ) )
2452 {
2453 const SvxLRSpaceItem& rLR = pParentFmt->GetLRSpace();
2454 nPageSize = pParentFmt->GetFrmSize().GetWidth() - rLR.GetLeft()
2455 - rLR.GetRight();
2456 }
2457 }
2458 else
2459 {
2460 nPageSize = aRect.Width();
2461 if ( bManualAligned )
2462 {
2463 // #i37571# For manually aligned tables
2464 const SvxLRSpaceItem &rLR = pFmt->GetLRSpace();
2465 nPageSize -= (rLR.GetLeft() + rLR.GetRight());
2466 }
2467
2468 }
2469
2470 ASSERT(nWidthPercent, "Impossible");
2471 if (nWidthPercent)
2472 {
2473 nPageSize *= nWidthPercent;
2474 nPageSize /= 100;
2475 }
2476 }
2477
2478 rPageSize = nPageSize;
2479 rRelBoxSize = bRelBoxSize;
2480 }
2481
TableDefaultBorders(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2482 void WW8AttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2483 {
2484 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2485 const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
2486
2487 //Set Default, just taken from the first cell of the first
2488 //row
2489 static sal_uInt16 aBorders[] =
2490 {
2491 BOX_LINE_TOP, BOX_LINE_LEFT,
2492 BOX_LINE_BOTTOM, BOX_LINE_RIGHT
2493 };
2494
2495 for ( int i = 0; i < 4; ++i )
2496 {
2497 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, 0xD634 );
2498 m_rWW8Export.pO->Insert( sal_uInt8(6), m_rWW8Export.pO->Count() );
2499 m_rWW8Export.pO->Insert( sal_uInt8(0), m_rWW8Export.pO->Count() );
2500 m_rWW8Export.pO->Insert( sal_uInt8(1), m_rWW8Export.pO->Count() );
2501 m_rWW8Export.pO->Insert( sal_uInt8(1 << i), m_rWW8Export.pO->Count() );
2502 m_rWW8Export.pO->Insert( sal_uInt8(3), m_rWW8Export.pO->Count() );
2503
2504 SwWW8Writer::InsUInt16( *m_rWW8Export.pO,
2505 pFrmFmt->GetBox().GetDistance( aBorders[i] ) );
2506 }
2507 }
2508
TableBackgrounds(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)2509 void WW8AttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2510 {
2511 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2512 const SwTableLine * pTabLine = pTabBox->GetUpper();
2513 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2514
2515 const sal_uInt16 nBoxes = rTabBoxes.Count();
2516 if ( m_rWW8Export.bWrtWW8 )
2517 m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTableShd );
2518 else
2519 m_rWW8Export.pO->Insert( (sal_uInt8)191, m_rWW8Export.pO->Count() );
2520 m_rWW8Export.pO->Insert( (sal_uInt8)(nBoxes * 2), m_rWW8Export.pO->Count() ); // Len
2521
2522 for ( sal_uInt8 n = 0; n < nBoxes; n++ )
2523 {
2524 const SwTableBox * pBox1 = rTabBoxes[n];
2525 const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
2526 const SfxPoolItem * pI = NULL;
2527 Color aColor;
2528
2529 if ( SFX_ITEM_ON == pFrmFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
2530 {
2531 aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
2532 }
2533 else
2534 aColor = COL_AUTO;
2535
2536 WW8_SHD aShd;
2537 m_rWW8Export.TransBrush( aColor, aShd );
2538 m_rWW8Export.InsUInt16( aShd.GetValue() );
2539 }
2540
2541 if ( m_rWW8Export.bWrtWW8 )
2542 {
2543 const sal_uInt16 aSprmIds[] = { NS_sprm::LN_TCellShd, NS_sprm::LN_TCellShadow };
2544 sal_uInt16 nBoxes0 = rTabBoxes.Count();
2545 if (nBoxes0 > 21)
2546 nBoxes0 = 21;
2547
2548 for ( sal_uInt32 m = 0; m < 2; m++ )
2549 {
2550 m_rWW8Export.InsUInt16( aSprmIds[m] );
2551 m_rWW8Export.pO->Insert(
2552 static_cast< sal_uInt8 >( nBoxes0 * 10 ),
2553 m_rWW8Export.pO->Count() );
2554
2555 for ( sal_uInt16 n = 0; n < nBoxes0; n++ )
2556 {
2557 const SwTableBox * pBox1 = rTabBoxes[n];
2558 const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
2559 const SfxPoolItem * pI = NULL;
2560 Color aColor;
2561
2562 if ( SFX_ITEM_ON ==
2563 pFrmFmt->GetAttrSet().
2564 GetItemState( RES_BACKGROUND, false, &pI ) )
2565 {
2566 aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
2567 }
2568 else
2569 aColor = COL_AUTO;
2570
2571 WW8SHDLong aSHD;
2572 aSHD.setCvFore( 0xFF000000 );
2573
2574 sal_uInt32 nBgColor = aColor.GetColor();
2575 if ( nBgColor == COL_AUTO )
2576 aSHD.setCvBack( 0xFF000000 );
2577 else
2578 aSHD.setCvBack( wwUtility::RGBToBGR( nBgColor ) );
2579
2580 aSHD.Write( m_rWW8Export );
2581 }
2582 }
2583 }
2584 }
2585
SectionBreaksAndFrames(const SwTxtNode & rNode)2586 void WW8Export::SectionBreaksAndFrames( const SwTxtNode& rNode )
2587 {
2588 // output page/section breaks
2589 OutputSectionBreaks( rNode.GetpSwAttrSet(), rNode );
2590
2591 // all textframes anchored as character for the winword 7- format
2592 if ( !bWrtWW8 && !IsInTable() )
2593 OutWW6FlyFrmsInCntnt( rNode );
2594 }
2595
2596 #ifdef DEBUG
2597 struct SwNodeHash
2598 {
operator ()SwNodeHash2599 size_t operator()(SwNode * pNode) const { return reinterpret_cast<size_t>(pNode); }
2600 };
2601
2602 typedef ::std::hash_set<SwNode *, SwNodeHash> SwNodeHashSet;
2603 typedef ::std::deque<SwNode *> SwNodeDeque;
2604 #endif
2605
WriteText()2606 void MSWordExportBase::WriteText()
2607 {
2608 // whoever has need of the missing function should go and implement it!
2609 // This piece of code always breaks builds...
2610 //#ifdef DEBUG
2611 // ::std::clog << "<WriteText>" << ::std::endl;
2612 // ::std::clog << dbg_out(pCurPam->GetDoc()->GetNodes()) << ::std::endl;
2613 //
2614 // SwNodeHashSet aNodeSet;
2615 // SwNodeDeque aNodeDeque;
2616 //#endif
2617
2618 while( pCurPam->GetPoint()->nNode < pCurPam->GetMark()->nNode ||
2619 ( pCurPam->GetPoint()->nNode == pCurPam->GetMark()->nNode &&
2620 pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex() ) )
2621 {
2622 SwNode * pNd = pCurPam->GetNode();
2623
2624 // whoever has need of the missing function should go and implement it!
2625 // This piece of code always breaks builds...
2626 #if 0
2627 #ifdef DEBUG
2628 if (aNodeSet.find(pNd) == aNodeSet.end())
2629 {
2630 aNodeSet.insert(pNd);
2631 aNodeDeque.push_back(pNd);
2632 }
2633 else
2634 {
2635 ::std::clog << "<already-done>" << dbg_out(*pNd) << "</already-done>" << ::std::endl;
2636 }
2637 #endif
2638 #endif
2639
2640 if ( pNd->IsTxtNode() )
2641 SectionBreaksAndFrames( *pNd->GetTxtNode() );
2642
2643 // output the various types of nodes
2644 if ( pNd->IsCntntNode() )
2645 {
2646 SwCntntNode* pCNd = (SwCntntNode*)pNd;
2647
2648 const SwPageDesc* pTemp = pCNd->GetSwAttrSet().GetPageDesc().GetPageDesc();
2649 if ( pTemp )
2650 pAktPageDesc = pTemp;
2651
2652 pCurPam->GetPoint()->nContent.Assign( pCNd, 0 );
2653 OutputContentNode( *pCNd );
2654 }
2655 else if ( pNd->IsTableNode() )
2656 {
2657 mpTableInfo->processSwTable( &pNd->GetTableNode()->GetTable() );
2658 }
2659 else if ( pNd->IsSectionNode() && TXT_MAINTEXT == nTxtTyp )
2660 OutputSectionNode( *pNd->GetSectionNode() );
2661 else if ( TXT_MAINTEXT == nTxtTyp && pNd->IsEndNode() &&
2662 pNd->StartOfSectionNode()->IsSectionNode() )
2663 {
2664 const SwSection& rSect = pNd->StartOfSectionNode()->GetSectionNode()
2665 ->GetSection();
2666 if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
2667 bStartTOX = false;
2668
2669 SwNodeIndex aIdx( *pNd, 1 );
2670 if ( aIdx.GetNode().IsEndNode() && aIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
2671 ;
2672 else if ( aIdx.GetNode().IsSectionNode() )
2673 ;
2674 else if ( !IsInTable()
2675 && (rSect.GetType() != TOX_CONTENT_SECTION && rSect.GetType() != TOX_HEADER_SECTION )) //No sections in table
2676 {
2677 //#120140# Do not need to insert a page/section break after a section end. Check this case first
2678 sal_Bool bNeedExportBreakHere = sal_True;
2679 if ( aIdx.GetNode().IsTxtNode() )
2680 {
2681 SwTxtNode *pTempNext = aIdx.GetNode().GetTxtNode();
2682 if ( pTempNext )
2683 {
2684 const SfxPoolItem * pTempItem = NULL;
2685 if (pTempNext->GetpSwAttrSet() && SFX_ITEM_SET == pTempNext->GetpSwAttrSet()->GetItemState(RES_PAGEDESC, false, &pTempItem)
2686 && pTempItem && ((SwFmtPageDesc*)pTempItem)->GetRegisteredIn())
2687 {
2688 //Next node has a new page style which means this node is a section end. Do not insert another page/section break here
2689 bNeedExportBreakHere = sal_False;
2690 }
2691 }
2692 }
2693 if (bNeedExportBreakHere) //#120140# End of check
2694 {
2695 ReplaceCr( (char)0xc ); // Indikator fuer Page/Section-Break
2696
2697 const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
2698 if ( !pParentFmt )
2699 pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
2700
2701 sal_uLong nRstLnNum;
2702 if ( aIdx.GetNode().IsCntntNode() )
2703 nRstLnNum = ((SwCntntNode&)aIdx.GetNode()).GetSwAttrSet().
2704 GetLineNumber().GetStartValue();
2705 else
2706 nRstLnNum = 0;
2707
2708 AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
2709 }
2710 }
2711 }
2712 else if ( pNd->IsStartNode() )
2713 {
2714 OutputStartNode( *pNd->GetStartNode() );
2715 }
2716 else if ( pNd->IsEndNode() )
2717 {
2718 OutputEndNode( *pNd->GetEndNode() );
2719 }
2720
2721 if ( pNd == &pNd->GetNodes().GetEndOfContent() )
2722 break;
2723
2724 SwNode * pCurrentNode = &pCurPam->GetPoint()->nNode.GetNode();
2725 const SwNode * pNextNode = mpTableInfo->getNextNode(pCurrentNode);
2726
2727 if (pNextNode != NULL)
2728 pCurPam->GetPoint()->nNode = SwNodeIndex(*pNextNode);
2729 else
2730 pCurPam->GetPoint()->nNode++;
2731
2732 sal_uLong nPos = pCurPam->GetPoint()->nNode.GetIndex();
2733 ::SetProgressState( nPos, pCurPam->GetDoc()->GetDocShell() );
2734 }
2735
2736 #ifdef DEBUG
2737 ::std::clog << "</WriteText>" << ::std::endl;
2738 #endif
2739 }
2740
WriteMainText()2741 void WW8Export::WriteMainText()
2742 {
2743 #ifdef DEBUG
2744 ::std::clog << "<WriteMainText>" << ::std::endl;
2745 #endif
2746
2747 pFib->fcMin = Strm().Tell();
2748
2749 pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
2750
2751 WriteText();
2752
2753 if( 0 == Strm().Tell() - pFib->fcMin ) // kein Text ?
2754 WriteCR(); // dann CR ans Ende ( sonst mault WW )
2755
2756 pFib->ccpText = Fc2Cp( Strm().Tell() );
2757 pFldMain->Finish( pFib->ccpText, 0 );
2758
2759 // ccpText beinhaltet Ftn- und KF-Texte
2760 // deshalb wird pFib->ccpText evtl. noch geupdated
2761 // save the StyleId of the last paragraph. Because WW97 take the style
2762 // from the last CR, that will be write after footer/Header/fontnotes/
2763 // annotation usw.
2764 const SwTxtNode* pLastNd = pCurPam->GetMark()->nNode.GetNode().GetTxtNode();
2765 if( pLastNd )
2766 nLastFmtId = GetId( (SwTxtFmtColl&)pLastNd->GetAnyFmtColl() );
2767
2768 #ifdef DEBUG
2769 ::std::clog << "</WriteMainText>" << ::std::endl;
2770 #endif
2771 }
2772
IsInTable() const2773 bool MSWordExportBase::IsInTable() const
2774 {
2775 bool bResult = false;
2776
2777 if (pCurPam != NULL)
2778 {
2779 SwNode * pNode = pCurPam->GetNode();
2780
2781 if (pNode != NULL && mpTableInfo.get() != NULL)
2782 {
2783 ww8::WW8TableNodeInfo::Pointer_t pTableNodeInfo = mpTableInfo->getTableNodeInfo(pNode);
2784
2785 if (pTableNodeInfo.get() != NULL && pTableNodeInfo->getDepth() > 0)
2786 {
2787 bResult = true;
2788 }
2789 }
2790 }
2791
2792 return bResult;
2793 }
2794
2795 typedef ww8::WW8Sttb< ww8::WW8Struct > WW8SttbAssoc;
2796
WriteFkpPlcUsw()2797 void WW8Export::WriteFkpPlcUsw()
2798 {
2799 if( !bWrtWW8 )
2800 {
2801 static const sal_uInt8 aSpec[2] =
2802 {
2803 117, 1
2804 };
2805
2806 pChpPlc->AppendFkpEntry( Strm().Tell() ); // Sepx mit fSpecial
2807 pSepx->WriteSepx( Strm() ); // Slcx.Sepx
2808 pGrf->Write(); // Grafiken
2809 pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec ), aSpec );
2810
2811 pChpPlc->WriteFkps(); // Fkp.Chpx
2812 pPapPlc->WriteFkps(); // Fkp.Papx
2813 pStyles->OutputStylesTable(); // Styles
2814 pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
2815 pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
2816 pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
2817 pSepx->WritePlcSed( *this ); // Slcx.PlcSed
2818 pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
2819 pChpPlc->WritePlc(); // Plcx.Chpx
2820 pPapPlc->WritePlc(); // Plcx.Papx
2821 maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
2822 if( pRedlAuthors )
2823 pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2824 pFldMain->Write( *this ); // Fields ( Main Text )
2825 pFldHdFt->Write( *this ); // Fields ( Header/Footer )
2826 pFldFtn->Write( *this ); // Fields ( FootNotes )
2827 pFldEdn->Write( *this ); // Fields ( EndNotes )
2828 pFldAtn->Write( *this ); // Fields ( Annotations )
2829 pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
2830 // plcfBkmkf/plcfBkmkl
2831 WriteDop( *this ); // Document-Properties
2832
2833 }
2834 else
2835 {
2836 // Grafiken in den Data-Tream
2837 pGrf->Write(); // Grafiken
2838
2839 // Ausgabe in WordDocument-Stream
2840 pChpPlc->WriteFkps(); // Fkp.Chpx
2841 pPapPlc->WriteFkps(); // Fkp.Papx
2842 pSepx->WriteSepx( Strm() ); // Sepx
2843
2844 // Ausagbe in Table-Stream
2845 pStyles->OutputStylesTable(); // fuer WW8 StyleTab
2846 pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
2847 pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
2848 pTxtBxs->WritePlc( *this ); // Textbox Text Plc
2849 pHFTxtBxs->WritePlc( *this ); // Head/Foot-Textbox Text Plc
2850 pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
2851
2852 pSepx->WritePlcSed( *this ); // Slcx.PlcSed
2853 pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
2854
2855 pChpPlc->WritePlc(); // Plcx.Chpx
2856 pPapPlc->WritePlc(); // Plcx.Papx
2857
2858 if( pRedlAuthors )
2859 pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2860 pFldMain->Write( *this ); // Fields ( Main Text )
2861 pFldHdFt->Write( *this ); // Fields ( Header/Footer )
2862 pFldFtn->Write( *this ); // Fields ( FootNotes )
2863 pFldEdn->Write( *this ); // Fields ( EndNotes )
2864 pFldAtn->Write( *this ); // Fields ( Annotations )
2865 pFldTxtBxs->Write( *this ); // Fields ( Textboxes )
2866 pFldHFTxtBxs->Write( *this ); // Fields ( Head/Foot-Textboxes )
2867
2868 if (pEscher || pDoc->ContainsMSVBasic())
2869 {
2870 /*
2871 #82587# Everytime MS 2000 creates an escher stream there is always
2872 an ObjectPool dir (even if empty). It turns out that if a copy of
2873 MS 2000 is used to open a document that contains escher graphics
2874 exported from StarOffice without this empty dir then *if* that
2875 copy of MS Office has never been used to open a MSOffice document
2876 that has escher graphics (and an ObjectPool dir of course) and
2877 that copy of office has not been used to draw escher graphics then
2878 our exported graphics do not appear. Once you do open a ms
2879 document with escher graphics or draw an escher graphic with that
2880 copy of word, then all documents from staroffice that contain
2881 escher work from then on. Tricky to track down, some sort of late
2882 binding trickery in MS where solely for first time initialization
2883 the existence of an ObjectPool dir is necessary for triggering
2884 some magic. cmc
2885 */
2886 /*
2887 #10570# Similiarly having msvbasic storage seems to also trigger
2888 creating this stream
2889 */
2890 GetWriter().GetStorage().OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool),
2891 STREAM_READWRITE | STREAM_SHARE_DENYALL);
2892 }
2893
2894 // dggInfo - escher stream
2895 WriteEscher();
2896
2897 pSdrObjs->WritePlc( *this );
2898 pHFSdrObjs->WritePlc( *this );
2899 // spamom - office drawing table
2900 // spahdr - header office drawing table
2901
2902 pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
2903 // plcfBkmkf/plcfBkmkl
2904
2905 WriteNumbering();
2906
2907 RestoreMacroCmds();
2908
2909 pMagicTable->Write( *this );
2910
2911 pPiece->WritePc( *this ); // Piece-Table
2912 maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
2913
2914 //Convert OOo asian typography into MS typography structure
2915 ExportDopTypography(pDop->doptypography);
2916
2917 WriteDop( *this ); // Document-Properties
2918
2919 // Write SttbfAssoc
2920 WW8SttbAssoc * pSttbfAssoc = dynamic_cast<WW8SttbAssoc *>
2921 (pDoc->getExternalData(::sw::STTBF_ASSOC).get());
2922 // --> OD 2009-10-19 #i106057#
2923 if ( pSttbfAssoc )
2924 // <--
2925 {
2926 ::std::vector<String> aStrings;
2927
2928 ::ww8::StringVector_t & aSttbStrings = pSttbfAssoc->getStrings();
2929 ::ww8::StringVector_t::const_iterator aItEnd = aSttbStrings.end();
2930 for (::ww8::StringVector_t::const_iterator aIt = aSttbStrings.begin();
2931 aIt != aItEnd; aIt++)
2932 {
2933 String aStr(aIt->getStr());
2934 aStrings.push_back(aStr);
2935 }
2936
2937 WriteAsStringTable(aStrings, pFib->fcSttbfAssoc,
2938 pFib->lcbSttbfAssoc);
2939 }
2940 }
2941 Strm().Seek( 0 );
2942
2943 // Reclaim stored FIB data from document.
2944 ::ww8::WW8FibData * pFibData = dynamic_cast<ww8::WW8FibData *>
2945 (pDoc->getExternalData(::sw::FIB).get());
2946
2947 if ( pFibData )
2948 // <--
2949 {
2950 pFib->fReadOnlyRecommended =
2951 pFibData->getReadOnlyRecommended() ? 1 : 0;
2952 pFib->fWriteReservation =
2953 pFibData->getWriteReservation() ? 1 : 0;
2954 }
2955
2956 pFib->Write( Strm() ); // FIB
2957 }
2958
StoreDoc1()2959 void WW8Export::StoreDoc1()
2960 {
2961 bool bNeedsFinalPara = false;
2962 // Start of Text ( Mangel ueber )
2963 SwWW8Writer::FillUntil( Strm(), pFib->fcMin );
2964
2965 WriteMainText(); // HauptText
2966 sal_uInt8 nSprmsLen;
2967 sal_uInt8 *pLastSprms = pPapPlc->CopyLastSprms(nSprmsLen);
2968
2969 bNeedsFinalPara |= pFtn->WriteTxt( *this ); // Footnote-Text
2970 bNeedsFinalPara |= pSepx->WriteKFTxt( *this ); // K/F-Text
2971 bNeedsFinalPara |= pAtn->WriteTxt( *this ); // Annotation-Text
2972 bNeedsFinalPara |= pEdn->WriteTxt( *this ); // EndNote-Text
2973
2974 // create the escher streams
2975 if( bWrtWW8 )
2976 CreateEscher();
2977
2978 bNeedsFinalPara |= pTxtBxs->WriteTxt( *this ); //Textbox Text Plc
2979 bNeedsFinalPara |= pHFTxtBxs->WriteTxt( *this );//Head/Foot-Textbox Text Plc
2980
2981 if (bNeedsFinalPara)
2982 {
2983 WriteCR();
2984 pPapPlc->AppendFkpEntry(Strm().Tell(), nSprmsLen, pLastSprms);
2985 }
2986 delete[] pLastSprms;
2987
2988 pSepx->Finish( Fc2Cp( Strm().Tell() ));// Text + Ftn + HdFt als Section-Ende
2989 pMagicTable->Finish( Fc2Cp( Strm().Tell() ),0);
2990
2991 pFib->fcMac = Strm().Tell(); // Ende aller Texte
2992
2993 WriteFkpPlcUsw(); // FKP, PLC, .....
2994 }
2995
AddLinkTarget(const String & rURL)2996 void MSWordExportBase::AddLinkTarget(const String& rURL)
2997 {
2998 if( !rURL.Len() || rURL.GetChar(0) != INET_MARK_TOKEN )
2999 return;
3000
3001 String aURL( BookmarkToWriter( rURL.Copy( 1 ) ) );
3002 xub_StrLen nPos = aURL.SearchBackward( cMarkSeperator );
3003
3004 if( nPos < 2 )
3005 return;
3006
3007 String sCmp( aURL.Copy( nPos+1 ) );
3008 sCmp.EraseAllChars();
3009 if( !sCmp.Len() )
3010 return;
3011
3012 sCmp.ToLowerAscii();
3013
3014 if( sCmp.EqualsAscii( pMarkToOutline ) )
3015 {
3016 SwPosition aPos( *pCurPam->GetPoint() );
3017 String aOutline( BookmarkToWriter(aURL.Copy( 0, nPos )) );
3018 // If we can find the outline this bookmark refers to
3019 // save the name of the bookmark and the
3020 // node index number of where it points to
3021 if( pDoc->GotoOutline( aPos, aOutline ) )
3022 {
3023 sal_uLong nIdx = aPos.nNode.GetIndex();
3024 aPair aImplicitBookmark;
3025 aImplicitBookmark.first = aOutline;
3026 aImplicitBookmark.second = nIdx;
3027 maImplicitBookmarks.push_back(aImplicitBookmark);
3028 }
3029 }
3030 }
3031
CollectOutlineBookmarks(const SwDoc & rDoc)3032 void MSWordExportBase::CollectOutlineBookmarks(const SwDoc &rDoc)
3033 {
3034 const SwFmtINetFmt* pINetFmt;
3035 const SwTxtINetFmt* pTxtAttr;
3036 const SwTxtNode* pTxtNd;
3037
3038 sal_uInt32 n, nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
3039 for( n = 0; n < nMaxItems; ++n )
3040 {
3041 if( 0 != (pINetFmt = (SwFmtINetFmt*)rDoc.GetAttrPool().GetItem2(
3042 RES_TXTATR_INETFMT, n ) ) &&
3043 0 != ( pTxtAttr = pINetFmt->GetTxtINetFmt()) &&
3044 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
3045 pTxtNd->GetNodes().IsDocNodes() )
3046 {
3047 AddLinkTarget( pINetFmt->GetValue() );
3048 }
3049 }
3050
3051 const SwFmtURL *pURL;
3052 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_URL );
3053 for( n = 0; n < nMaxItems; ++n )
3054 {
3055 if( 0 != (pURL = (SwFmtURL*)rDoc.GetAttrPool().GetItem2(
3056 RES_URL, n ) ) )
3057 {
3058 AddLinkTarget( pURL->GetURL() );
3059 const ImageMap *pIMap = pURL->GetMap();
3060 if( pIMap )
3061 {
3062 for( sal_uInt16 i=0; i<pIMap->GetIMapObjectCount(); i++ )
3063 {
3064 const IMapObject* pObj = pIMap->GetIMapObject( i );
3065 if( pObj )
3066 {
3067 AddLinkTarget( pObj->GetURL() );
3068 }
3069 }
3070 }
3071 }
3072 }
3073 }
3074
3075 namespace
3076 {
3077 const sal_uLong WW_BLOCKSIZE = 0x200;
3078
EncryptRC4(msfilter::MSCodec_Std97 & rCtx,SvStream & rIn,SvStream & rOut)3079 void EncryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
3080 {
3081 rIn.Seek(STREAM_SEEK_TO_END);
3082 sal_uLong nLen = rIn.Tell();
3083 rIn.Seek(0);
3084
3085 sal_uInt8 in[WW_BLOCKSIZE];
3086 for (sal_uLong nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
3087 {
3088 sal_uLong nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
3089 rIn.Read(in, nBS);
3090 rCtx.InitCipher(nBlock);
3091 rCtx.Encode(in, nBS, in, nBS);
3092 rOut.Write(in, nBS);
3093 }
3094 }
3095 }
3096
ExportDocument(bool bWriteAll)3097 void MSWordExportBase::ExportDocument( bool bWriteAll )
3098 {
3099 nCharFmtStart = ANZ_DEFAULT_STYLES;
3100 nFmtCollStart = nCharFmtStart + pDoc->GetCharFmts()->Count() - 1;
3101
3102 bStyDef = bBreakBefore = bOutKF =
3103 bOutFlyFrmAttrs = bOutPageDescs = bOutTable = bOutFirstPage =
3104 bOutGrf = bInWriteEscher = bStartTOX =
3105 bInWriteTOX = false;
3106
3107 bFtnAtTxtEnd = bEndAtTxtEnd = true;
3108
3109 mpParentFrame = 0;
3110 pFlyOffset = 0;
3111 eNewAnchorType = FLY_AT_PAGE;
3112 nTxtTyp = TXT_MAINTEXT;
3113 nStyleBeforeFly = nLastFmtId = 0;
3114 pStyAttr = 0;
3115 pCurrentStyle = NULL;
3116 pOutFmtNode = 0;
3117 pEscher = 0;
3118 pRedlAuthors = 0;
3119 if ( aTOXArr.Count() )
3120 aTOXArr.Remove( 0, aTOXArr.Count() );
3121
3122 // update layout as it is needed for the export - e.g. for the export of tables
3123 boost::scoped_ptr< ViewShell > pTemporaryViewShell( 0 );
3124 {
3125 ViewShell* pViewShell = NULL;
3126 pDoc->GetEditShell( &pViewShell );
3127 if ( pViewShell == NULL )
3128 {
3129 pTemporaryViewShell.reset( new ViewShell( *pDoc, 0 ) );
3130 pViewShell = pTemporaryViewShell.get();
3131 }
3132 if ( pViewShell != NULL )
3133 {
3134 pViewShell->CalcLayout();
3135 }
3136 }
3137
3138 if ( !pOLEExp )
3139 {
3140 sal_uInt32 nSvxMSDffOLEConvFlags = 0;
3141 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
3142 if ( pOpt->IsMath2MathType() )
3143 nSvxMSDffOLEConvFlags |= OLE_STARMATH_2_MATHTYPE;
3144 if ( pOpt->IsWriter2WinWord() )
3145 nSvxMSDffOLEConvFlags |= OLE_STARWRITER_2_WINWORD;
3146 if ( pOpt->IsCalc2Excel() )
3147 nSvxMSDffOLEConvFlags |= OLE_STARCALC_2_EXCEL;
3148 if ( pOpt->IsImpress2PowerPoint() )
3149 nSvxMSDffOLEConvFlags |= OLE_STARIMPRESS_2_POWERPOINT;
3150
3151 pOLEExp = new SvxMSExportOLEObjects( nSvxMSDffOLEConvFlags );
3152 }
3153
3154 if ( !pOleMap)
3155 pOleMap = new WW8OleMaps;
3156
3157 if ( !pOCXExp )
3158 pOCXExp = new SwMSConvertControls( pDoc->GetDocShell(), pCurPam );
3159
3160 // Collect anchored objects before changing the redline mode.
3161 maFrames = GetFrames( *pDoc, bWriteAll? NULL : pOrigPam );
3162
3163 mnRedlineMode = pDoc->GetRedlineMode();
3164 if ( pDoc->GetRedlineTbl().Count() )
3165 {
3166 pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode | nsRedlineMode_t::REDLINE_SHOW_DELETE |
3167 nsRedlineMode_t::REDLINE_SHOW_INSERT) );
3168 }
3169
3170 maFontHelper.InitFontTable( HackIsWW8OrHigher(), *pDoc );
3171 GatherChapterFields();
3172
3173 CollectOutlineBookmarks(*pDoc);
3174
3175 // make unique OrdNums (Z-Order) for all drawing-/fly Objects
3176 if ( pDoc->GetDrawModel() )
3177 pDoc->GetDrawModel()->GetPage( 0 )->RecalcObjOrdNums();
3178
3179 ExportDocument_Impl();
3180
3181 if ( mnRedlineMode != pDoc->GetRedlineMode() )
3182 pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode) );
3183 }
3184
InitStd97CodecUpdateMedium(::msfilter::MSCodec_Std97 & rCodec)3185 bool SwWW8Writer::InitStd97CodecUpdateMedium( ::msfilter::MSCodec_Std97& rCodec )
3186 {
3187 uno::Sequence< beans::NamedValue > aEncryptionData;
3188
3189 if ( mpMedium )
3190 {
3191 SFX_ITEMSET_ARG( mpMedium->GetItemSet(), pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
3192 if ( pEncryptionDataItem && ( pEncryptionDataItem->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
3193 {
3194 OSL_ENSURE( false, "Unexpected EncryptionData!" );
3195 aEncryptionData.realloc( 0 );
3196 }
3197
3198 if ( !aEncryptionData.getLength() )
3199 {
3200 // try to generate the encryption data based on password
3201 SFX_ITEMSET_ARG( mpMedium->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False );
3202 if ( pPasswordItem && pPasswordItem->GetValue().Len() && pPasswordItem->GetValue().Len() <= 15 )
3203 {
3204 // Generate random number with a seed of time as salt.
3205 TimeValue aTime;
3206 osl_getSystemTime( &aTime );
3207 rtlRandomPool aRandomPool = rtl_random_createPool ();
3208 rtl_random_addBytes ( aRandomPool, &aTime, 8 );
3209
3210 sal_uInt8 pDocId[ 16 ];
3211 rtl_random_getBytes( aRandomPool, pDocId, 16 );
3212
3213 rtl_random_destroyPool( aRandomPool );
3214
3215 sal_Unicode aPassword[16];
3216 memset( aPassword, 0, sizeof( aPassword ) );
3217 for ( xub_StrLen nChar = 0; nChar < pPasswordItem->GetValue().Len(); ++nChar )
3218 aPassword[nChar] = pPasswordItem->GetValue().GetChar(nChar);
3219
3220 rCodec.InitKey( aPassword, pDocId );
3221 aEncryptionData = rCodec.GetEncryptionData();
3222
3223 mpMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
3224 }
3225 }
3226
3227 if ( aEncryptionData.getLength() )
3228 mpMedium->GetItemSet()->ClearItem( SID_PASSWORD );
3229 }
3230
3231 // nonempty encryption data means hier that the codec was successfuly initialized
3232 return ( aEncryptionData.getLength() != 0 );
3233 }
3234
ExportDocument_Impl()3235 void WW8Export::ExportDocument_Impl()
3236 {
3237 PrepareStorage();
3238
3239 pFib = new WW8Fib( bWrtWW8 ? 8 : 6 );
3240
3241 SvStorageStreamRef xWwStrm( GetWriter().GetStorage().OpenSotStream( aMainStg ) );
3242 SvStorageStreamRef xTableStrm( xWwStrm ), xDataStrm( xWwStrm );
3243 xWwStrm->SetBufferSize( 32768 );
3244
3245 if( bWrtWW8 )
3246 {
3247 pFib->fWhichTblStm = 1;
3248 xTableStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::a1Table),
3249 STREAM_STD_WRITE );
3250 xDataStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::aData),
3251 STREAM_STD_WRITE );
3252
3253 xDataStrm->SetBufferSize( 32768 ); // fuer Grafiken
3254 xTableStrm->SetBufferSize( 16384 ); // fuer die Font-/Style-Table, usw.
3255
3256 xTableStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3257 xDataStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3258 }
3259
3260 GetWriter().SetStream( & *xWwStrm );
3261 pTableStrm = &xTableStrm;
3262 pDataStrm = &xDataStrm;
3263
3264 Strm().SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3265
3266 utl::TempFile aTempMain;
3267 aTempMain.EnableKillingFile();
3268 utl::TempFile aTempTable;
3269 aTempTable.EnableKillingFile();
3270 utl::TempFile aTempData;
3271 aTempData.EnableKillingFile();
3272
3273 msfilter::MSCodec_Std97 aCtx;
3274 bool bEncrypt = m_pWriter ? m_pWriter->InitStd97CodecUpdateMedium( aCtx ) : false;
3275 if ( bEncrypt )
3276 {
3277 GetWriter().SetStream(
3278 aTempMain.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE ) );
3279
3280 pTableStrm = aTempTable.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
3281
3282 pDataStrm = aTempData.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
3283
3284 sal_uInt8 aRC4EncryptionHeader[ 52 ] = {0};
3285 pTableStrm->Write( aRC4EncryptionHeader, 52 );
3286 }
3287
3288 // Default: "Standard"
3289 pSepx = new WW8_WrPlcSepx( *this ); // Sections/headers/footers
3290
3291 pFtn = new WW8_WrPlcFtnEdn( TXT_FTN ); // Footnotes
3292 pEdn = new WW8_WrPlcFtnEdn( TXT_EDN ); // Endnotes
3293 pAtn = new WW8_WrPlcAnnotations; // PostIts
3294 pTxtBxs = new WW8_WrPlcTxtBoxes( TXT_TXTBOX );
3295 pHFTxtBxs = new WW8_WrPlcTxtBoxes( TXT_HFTXTBOX );
3296
3297 pSdrObjs = new MainTxtPlcDrawObj; // Draw-/Fly-Objects for main text
3298 pHFSdrObjs = new HdFtPlcDrawObj; // Draw-/Fly-Objects for header/footer
3299
3300 pBkmks = new WW8_WrtBookmarks; // Bookmarks
3301 GetWriter().CreateBookmarkTbl();
3302
3303 pPapPlc = new WW8_WrPlcPn( *this, PAP, pFib->fcMin );
3304 pChpPlc = new WW8_WrPlcPn( *this, CHP, pFib->fcMin );
3305 pO = new WW8Bytes( 128, 128 );
3306 pStyles = new MSWordStyles( *this );
3307 pFldMain = new WW8_WrPlcFld( 2, TXT_MAINTEXT );
3308 pFldHdFt = new WW8_WrPlcFld( 2, TXT_HDFT );
3309 pFldFtn = new WW8_WrPlcFld( 2, TXT_FTN );
3310 pFldEdn = new WW8_WrPlcFld( 2, TXT_EDN );
3311 pFldAtn = new WW8_WrPlcFld( 2, TXT_ATN );
3312 pFldTxtBxs = new WW8_WrPlcFld( 2, TXT_TXTBOX );
3313 pFldHFTxtBxs = new WW8_WrPlcFld( 2, TXT_HFTXTBOX );
3314
3315 pMagicTable = new WW8_WrMagicTable;
3316
3317 pGrf = new SwWW8WrGrf( *this );
3318 pPiece = new WW8_WrPct( pFib->fcMin, bWrtWW8 );
3319 pDop = new WW8Dop;
3320
3321
3322 pDop->fRevMarking = 0 != ( nsRedlineMode_t::REDLINE_ON & mnRedlineMode );
3323 pDop->fRMView = 0 != ( nsRedlineMode_t::REDLINE_SHOW_DELETE & mnRedlineMode );
3324 pDop->fRMPrint = pDop->fRMView;
3325
3326 // set AutoHyphenation flag if found in default para style
3327 const SfxPoolItem* pItem;
3328 SwTxtFmtColl* pStdTxtFmtColl =
3329 pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false);
3330 if (pStdTxtFmtColl && SFX_ITEM_SET == pStdTxtFmtColl->GetItemState(
3331 RES_PARATR_HYPHENZONE, false, &pItem))
3332 {
3333 pDop->fAutoHyphen = ((const SvxHyphenZoneItem*)pItem)->IsHyphen();
3334 }
3335
3336 StoreDoc1();
3337
3338 if ( bEncrypt )
3339 {
3340 SvStream *pStrmTemp, *pTableStrmTemp, *pDataStrmTemp;
3341 pStrmTemp = &xWwStrm;
3342 pTableStrmTemp = &xTableStrm;
3343 pDataStrmTemp = &xDataStrm;
3344
3345 if ( pDataStrmTemp && pDataStrmTemp != pStrmTemp)
3346 EncryptRC4(aCtx, *pDataStrm, *pDataStrmTemp);
3347
3348 EncryptRC4(aCtx, *pTableStrm, *pTableStrmTemp);
3349
3350 // Write Unencrypted Header 52 bytes to the start of the table stream
3351 // EncryptionVersionInfo (4 bytes): A Version structure where Version.vMajor MUST be 0x0001, and Version.vMinor MUST be 0x0001.
3352 pTableStrmTemp->Seek( 0 );
3353 sal_uInt32 nEncType = 0x10001;
3354 *pTableStrmTemp << nEncType;
3355
3356 sal_uInt8 pDocId[16];
3357 aCtx.GetDocId( pDocId );
3358
3359 sal_uInt8 pSaltData[16];
3360 sal_uInt8 pSaltDigest[16];
3361 aCtx.GetEncryptKey( pDocId, pSaltData, pSaltDigest );
3362
3363 pTableStrmTemp->Write( pDocId, 16 );
3364 pTableStrmTemp->Write( pSaltData, 16 );
3365 pTableStrmTemp->Write( pSaltDigest, 16 );
3366
3367 EncryptRC4(aCtx, GetWriter().Strm(), *pStrmTemp);
3368
3369 // Write Unencrypted Fib 68 bytes to the start of the workdocument stream
3370 pFib->fEncrypted = 1; // fEncrypted indicates the document is encrypted.
3371 pFib->fObfuscated = 0; // Must be 0 for RC4.
3372 pFib->nHash = 0x34; // encrypt header bytes count of table stream.
3373 pFib->nKey = 0; // lkey2 must be 0 for RC4.
3374
3375 pStrmTemp->Seek( 0 );
3376 pFib->WriteHeader( *pStrmTemp );
3377 }
3378
3379 if (pUsedNumTbl) // all used NumRules
3380 {
3381 // clear the part of the list array that was copied from the document
3382 // - it's an auto delete array, so the rest of the array which are
3383 // duplicated lists that were added during the export will be deleted.
3384 pUsedNumTbl->Remove(0, pUsedNumTbl->Count()-nUniqueList);
3385 delete pUsedNumTbl;
3386 }
3387
3388 DELETEZ( pGrf );
3389 DELETEZ( pMagicTable );
3390 DELETEZ( pFldFtn );
3391 DELETEZ( pFldTxtBxs );
3392 DELETEZ( pFldHFTxtBxs );
3393 DELETEZ( pFldAtn );
3394 DELETEZ( pFldEdn );
3395 DELETEZ( pFldHdFt );
3396 DELETEZ( pFldMain );
3397 DELETEZ( pStyles );
3398 DELETEZ( pO );
3399 DELETEZ( pChpPlc );
3400 DELETEZ( pPapPlc );
3401 DELETEZ( pSepx );
3402
3403 delete pRedlAuthors;
3404 delete pSdrObjs;
3405 delete pHFSdrObjs;
3406 delete pTxtBxs;
3407 delete pHFTxtBxs;
3408 delete pAtn;
3409 delete pEdn;
3410 delete pFtn;
3411 delete pBkmks;
3412 delete pPiece;
3413 delete pDop;
3414 delete pFib;
3415 GetWriter().SetStream( 0 );
3416
3417
3418 xWwStrm->SetBufferSize( 0 );
3419 if( bWrtWW8 )
3420 {
3421 xTableStrm->SetBufferSize( 0 );
3422 xDataStrm->SetBufferSize( 0 );
3423 if( 0 == pDataStrm->Seek( STREAM_SEEK_TO_END ))
3424 {
3425 xDataStrm.Clear();
3426 pDataStrm = 0;
3427 GetWriter().GetStorage().Remove(CREATE_CONST_ASC(SL::aData));
3428 }
3429 }
3430 }
3431
3432
PrepareStorage()3433 void WW8Export::PrepareStorage()
3434 {
3435 sal_uLong nLen;
3436 const sal_uInt8* pData;
3437 const char* pName;
3438 sal_uInt32 nId1;
3439
3440 if (bWrtWW8)
3441 {
3442 static const char aUserName[] = "Microsoft Word-Document";
3443 static const sal_uInt8 aCompObj[] =
3444 {
3445 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3446 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x09, 0x02, 0x00,
3447 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3448 0x00, 0x00, 0x00, 0x46, 0x18, 0x00, 0x00, 0x00,
3449 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
3450 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x2D, 0x44,
3451 0x6F, 0x6B, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x00,
3452 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x53, 0x57, 0x6F,
3453 0x72, 0x64, 0x44, 0x6F, 0x63, 0x00, 0x10, 0x00,
3454 0x00, 0x00, 0x57, 0x6F, 0x72, 0x64, 0x2E, 0x44,
3455 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E,
3456 0x38, 0x00, 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00,
3457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3458 0x00, 0x00
3459 };
3460
3461 pName = aUserName;
3462 pData = aCompObj;
3463 nLen = sizeof( aCompObj );
3464 nId1 = 0x00020906L;
3465 }
3466 else
3467 {
3468 static const char aUserName[] = "Microsoft Word 6.0 Document";
3469 static const sal_uInt8 aCompObj[] =
3470 {
3471 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3472 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x09, 0x02, 0x00,
3473 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3474 0x00, 0x00, 0x00, 0x46, 0x1C, 0x00, 0x00, 0x00,
3475 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
3476 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x20, 0x36,
3477 0x2E, 0x30, 0x2D, 0x44, 0x6F, 0x6B, 0x75, 0x6D,
3478 0x65, 0x6E, 0x74, 0x00, 0x0A, 0x00, 0x00, 0x00,
3479 0x4D, 0x53, 0x57, 0x6F, 0x72, 0x64, 0x44, 0x6F,
3480 0x63, 0x00, 0x10, 0x00, 0x00, 0x00, 0x57, 0x6F,
3481 0x72, 0x64, 0x2E, 0x44, 0x6F, 0x63, 0x75, 0x6D,
3482 0x65, 0x6E, 0x74, 0x2E, 0x36, 0x00, 0x00, 0x00,
3483 0x00, 0x00
3484 };
3485
3486 pName = aUserName;
3487 pData = aCompObj;
3488 nLen = sizeof( aCompObj );
3489 nId1 = 0x00020900L;
3490 }
3491
3492 SvGlobalName aGName( nId1, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00,
3493 0x00, 0x00, 0x00, 0x46 );
3494 GetWriter().GetStorage().SetClass( aGName, 0, String::CreateFromAscii( pName ));
3495 SvStorageStreamRef xStor( GetWriter().GetStorage().OpenSotStream(sCompObj) );
3496 xStor->Write( pData, nLen );
3497
3498 SwDocShell* pDocShell = pDoc->GetDocShell ();
3499 DBG_ASSERT(pDocShell, "no SwDocShell");
3500
3501 if (pDocShell) {
3502 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3503 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
3504 uno::Reference<document::XDocumentProperties> xDocProps(
3505 xDPS->getDocumentProperties());
3506 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
3507
3508 if (xDocProps.is())
3509 {
3510 if ( SvtFilterOptions::Get()->IsEnableWordPreview() )
3511 {
3512 ::boost::shared_ptr<GDIMetaFile> pMetaFile =
3513 pDocShell->GetPreviewMetaFile (sal_False);
3514 uno::Sequence<sal_uInt8> metaFile(
3515 sfx2::convertMetaFile(pMetaFile.get()));
3516 sfx2::SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
3517 }
3518 else
3519 sfx2::SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
3520 }
3521 }
3522 }
3523
WriteStorage()3524 sal_uLong SwWW8Writer::WriteStorage()
3525 {
3526 long nMaxNode = pDoc->GetNodes().Count();
3527 ::StartProgress( STR_STATSTR_W4WWRITE, 0, nMaxNode, pDoc->GetDocShell() );
3528
3529 // Tabelle am Doc.-Anfang beachten
3530 {
3531 SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode();
3532 if( pTNd && bWriteAll )
3533 // mit dem TabellenNode anfangen !!
3534 pCurPam->GetPoint()->nNode = *pTNd;
3535 }
3536
3537 // Do the actual export
3538 {
3539 WW8Export aExport( this, pDoc, pCurPam, pOrigPam, m_bWrtWW8 );
3540 m_pExport = &aExport;
3541 aExport.ExportDocument( bWriteAll );
3542 m_pExport = NULL;
3543 }
3544
3545 ::EndProgress( pDoc->GetDocShell() );
3546 return 0;
3547 }
3548
WriteMedium(SfxMedium &)3549 sal_uLong SwWW8Writer::WriteMedium( SfxMedium& )
3550 {
3551 return WriteStorage();
3552 }
3553
Write(SwPaM & rPaM,SfxMedium & rMed,const String * pFileName)3554 sal_uLong SwWW8Writer::Write( SwPaM& rPaM, SfxMedium& rMed,
3555 const String* pFileName )
3556 {
3557 mpMedium = &rMed;
3558 sal_uLong nRet = StgWriter::Write( rPaM, rMed, pFileName );
3559 mpMedium = NULL;
3560 return nRet;
3561 }
3562
MSWordExportBase(SwDoc * pDocument,SwPaM * pCurrentPam,SwPaM * pOriginalPam)3563 MSWordExportBase::MSWordExportBase( SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
3564 : aMainStg(sMainStream), pISet(0), pUsedNumTbl(0), mpTopNodeOfHdFtPage(0),
3565 pBmpPal(0), pOLEExp(0), pOCXExp(0), pOleMap(0),
3566 mpTableInfo(new ww8::WW8TableInfo()), nUniqueList(0),
3567 mnHdFtIndex(0), pAktPageDesc(0), pPapPlc(0), pChpPlc(0), pChpIter(0),
3568 pStyles( NULL ),
3569 bHasHdr(false), bHasFtr(false), bSubstituteBullets(true),
3570 mbExportModeRTF( false ),
3571 mbOutOutlineOnly( false ),
3572 pDoc( pDocument ),
3573 pCurPam( pCurrentPam ),
3574 pOrigPam( pOriginalPam )
3575 {
3576 }
3577
~MSWordExportBase()3578 MSWordExportBase::~MSWordExportBase()
3579 {
3580 delete pBmpPal;
3581 delete pOLEExp;
3582 delete pOCXExp;
3583 delete pOleMap;
3584 }
3585
WW8Export(SwWW8Writer * pWriter,SwDoc * pDocument,SwPaM * pCurrentPam,SwPaM * pOriginalPam,bool bIsWW8)3586 WW8Export::WW8Export(
3587 SwWW8Writer *pWriter,
3588 SwDoc *pDocument,
3589 SwPaM *pCurrentPam,
3590 SwPaM *pOriginalPam,
3591 bool bIsWW8 )
3592 : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
3593 pO( NULL ),
3594 mpTableAt( NULL ),
3595 mnTableStdAtLen( 0 ),
3596 pSepx( NULL ),
3597 bWrtWW8( bIsWW8 ),
3598 m_pWriter( pWriter ),
3599 m_pAttrOutput( new WW8AttributeOutput( *this ) )
3600 {
3601 }
3602
~WW8Export()3603 WW8Export::~WW8Export()
3604 {
3605 delete m_pAttrOutput, m_pAttrOutput = NULL;
3606 }
3607
AttrOutput() const3608 AttributeOutputBase& WW8Export::AttrOutput() const
3609 {
3610 return *m_pAttrOutput;
3611 }
3612
Sections() const3613 MSWordSections& WW8Export::Sections() const
3614 {
3615 return *pSepx;
3616 }
3617
SwWW8Writer(const String & rFltName,const String & rBaseURL)3618 SwWW8Writer::SwWW8Writer(const String& rFltName, const String& rBaseURL)
3619 : StgWriter(),
3620 m_bWrtWW8( rFltName.EqualsAscii( FILTER_WW8 ) ),
3621 m_pExport( NULL ),
3622 mpMedium( 0 )
3623 {
3624 SetBaseURL( rBaseURL );
3625 }
3626
~SwWW8Writer()3627 SwWW8Writer::~SwWW8Writer()
3628 {
3629 }
3630
SaveOrDelMSVBAStorage_ww8(SfxObjectShell & rDoc,SotStorage & rStor,sal_Bool bSaveInto,const String & rStorageName)3631 extern "C" SAL_DLLPUBLIC_EXPORT sal_uLong SAL_CALL SaveOrDelMSVBAStorage_ww8( SfxObjectShell& rDoc, SotStorage& rStor, sal_Bool bSaveInto, const String& rStorageName )
3632 {
3633 SvxImportMSVBasic aTmp( rDoc, rStor );
3634 return aTmp.SaveOrDelMSVBAStorage( bSaveInto, rStorageName );
3635 }
3636
ExportDOC(const String & rFltName,const String & rBaseURL,WriterRef & xRet)3637 extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportDOC( const String& rFltName, const String& rBaseURL, WriterRef& xRet )
3638 {
3639 xRet = new SwWW8Writer( rFltName, rBaseURL );
3640 }
3641
3642
GetSaveWarningOfMSVBAStorage_ww8(SfxObjectShell & rDocS)3643 extern "C" SAL_DLLPUBLIC_EXPORT sal_uLong SAL_CALL GetSaveWarningOfMSVBAStorage_ww8( SfxObjectShell &rDocS )
3644 {
3645 return SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( rDocS );
3646 }
3647
WriteTxt(WW8Export & rWrt)3648 bool WW8_WrPlcFtnEdn::WriteTxt( WW8Export& rWrt )
3649 {
3650 bool bRet = false;
3651 if (TXT_FTN == nTyp)
3652 {
3653 bRet = WriteGenericTxt( rWrt, TXT_FTN, rWrt.pFib->ccpFtn );
3654 rWrt.pFldFtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3655 rWrt.pFib->ccpText );
3656 }
3657 else
3658 {
3659 bRet = WriteGenericTxt( rWrt, TXT_EDN, rWrt.pFib->ccpEdn );
3660 rWrt.pFldEdn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3661 rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
3662 + rWrt.pFib->ccpHdr + rWrt.pFib->ccpAtn );
3663 }
3664 return bRet;
3665 }
3666
WritePlc(WW8Export & rWrt) const3667 void WW8_WrPlcFtnEdn::WritePlc( WW8Export& rWrt ) const
3668 {
3669 if( TXT_FTN == nTyp )
3670 {
3671 WriteGenericPlc( rWrt, TXT_FTN, rWrt.pFib->fcPlcffndTxt,
3672 rWrt.pFib->lcbPlcffndTxt, rWrt.pFib->fcPlcffndRef,
3673 rWrt.pFib->lcbPlcffndRef );
3674 }
3675 else
3676 {
3677 WriteGenericPlc( rWrt, TXT_EDN, rWrt.pFib->fcPlcfendTxt,
3678 rWrt.pFib->lcbPlcfendTxt, rWrt.pFib->fcPlcfendRef,
3679 rWrt.pFib->lcbPlcfendRef );
3680 }
3681 }
3682
3683
WriteTxt(WW8Export & rWrt)3684 bool WW8_WrPlcAnnotations::WriteTxt( WW8Export& rWrt )
3685 {
3686 bool bRet = WriteGenericTxt( rWrt, TXT_ATN, rWrt.pFib->ccpAtn );
3687 rWrt.pFldAtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3688 rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
3689 + rWrt.pFib->ccpHdr );
3690 return bRet;
3691 }
3692
WritePlc(WW8Export & rWrt) const3693 void WW8_WrPlcAnnotations::WritePlc( WW8Export& rWrt ) const
3694 {
3695 WriteGenericPlc( rWrt, TXT_ATN, rWrt.pFib->fcPlcfandTxt,
3696 rWrt.pFib->lcbPlcfandTxt, rWrt.pFib->fcPlcfandRef,
3697 rWrt.pFib->lcbPlcfandRef );
3698 }
3699
WritePlc(WW8Export & rWrt) const3700 void WW8_WrPlcTxtBoxes::WritePlc( WW8Export& rWrt ) const
3701 {
3702 if( TXT_TXTBOX == nTyp )
3703 {
3704 WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcftxbxBkd,
3705 rWrt.pFib->lcbPlcftxbxBkd, rWrt.pFib->fcPlcftxbxTxt,
3706 rWrt.pFib->lcbPlcftxbxTxt );
3707 }
3708 else
3709 {
3710 WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcfHdrtxbxBkd,
3711 rWrt.pFib->lcbPlcfHdrtxbxBkd, rWrt.pFib->fcPlcfHdrtxbxTxt,
3712 rWrt.pFib->lcbPlcfHdrtxbxTxt );
3713 }
3714 }
3715
RestoreMacroCmds()3716 void WW8Export::RestoreMacroCmds()
3717 {
3718 pFib->fcCmds = pTableStrm->Tell();
3719
3720 uno::Reference < embed::XStorage > xSrcRoot(pDoc->GetDocShell()->GetStorage());
3721 try
3722 {
3723 uno::Reference < io::XStream > xSrcStream =
3724 xSrcRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READ );
3725 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xSrcStream );
3726
3727 if ( pStream && SVSTREAM_OK == pStream->GetError())
3728 {
3729 pStream->Seek(STREAM_SEEK_TO_END);
3730 pFib->lcbCmds = pStream->Tell();
3731 pStream->Seek(0);
3732
3733 sal_uInt8 *pBuffer = new sal_uInt8[pFib->lcbCmds];
3734 pStream->Read(pBuffer, pFib->lcbCmds);
3735 pTableStrm->Write(pBuffer, pFib->lcbCmds);
3736 delete[] pBuffer;
3737
3738 }
3739
3740 delete pStream;
3741 }
3742 catch ( uno::Exception& )
3743 {
3744 }
3745
3746 // set len to FIB
3747 pFib->lcbCmds = pTableStrm->Tell() - pFib->fcCmds;
3748 }
3749
Write(WW8Export & rExport)3750 void WW8SHDLong::Write( WW8Export& rExport )
3751 {
3752 rExport.InsUInt32( m_cvFore );
3753 rExport.InsUInt32( m_cvBack );
3754 rExport.InsUInt16( m_ipat );
3755 }
3756
WriteFormData(const::sw::mark::IFieldmark & rFieldmark)3757 void WW8Export::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
3758 {
3759 ASSERT( bWrtWW8, "No 95 export yet" );
3760 if ( !bWrtWW8 )
3761 return;
3762
3763 const ::sw::mark::IFieldmark* pFieldmark = &rFieldmark;
3764 const ::sw::mark::ICheckboxFieldmark* pAsCheckbox = dynamic_cast< const ::sw::mark::ICheckboxFieldmark* >( pFieldmark );
3765
3766
3767 ASSERT(rFieldmark.GetFieldname().equalsAscii( ODF_FORMTEXT ) || rFieldmark.GetFieldname().equalsAscii( ODF_FORMDROPDOWN ) || rFieldmark.GetFieldname().equalsAscii( ODF_FORMCHECKBOX ), "Unknown field type!!!");
3768 if ( ! ( rFieldmark.GetFieldname().equalsAscii( ODF_FORMTEXT ) ||
3769 rFieldmark.GetFieldname().equalsAscii( ODF_FORMDROPDOWN ) ||
3770 rFieldmark.GetFieldname().equalsAscii( ODF_FORMCHECKBOX ) ) )
3771 return;
3772
3773 int type = 0; // TextFieldmark
3774 if ( pAsCheckbox )
3775 type = 1;
3776 if ( rFieldmark.GetFieldname().equalsAscii( ODF_FORMDROPDOWN ) )
3777 type=2;
3778
3779 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pNameParameter = rFieldmark.GetParameters()->find(::rtl::OUString::createFromAscii("name"));
3780 ::rtl::OUString ffname;
3781 if(pNameParameter != rFieldmark.GetParameters()->end())
3782 pNameParameter->second >>= ffname;
3783
3784 sal_uLong nDataStt = pDataStrm->Tell();
3785 pChpPlc->AppendFkpEntry(Strm().Tell());
3786
3787 WriteChar(0x01);
3788 static sal_uInt8 aArr1[] =
3789 {
3790 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
3791
3792 0x06, 0x08, 0x01, // sprmCFData
3793 0x55, 0x08, 0x01, // sprmCFSpec
3794 0x02, 0x08, 0x01 // sprmCFFldVanish
3795 };
3796 sal_uInt8* pDataAdr = aArr1 + 2;
3797 Set_UInt32(pDataAdr, nDataStt);
3798
3799 pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aArr1 ), aArr1 );
3800
3801 sal_uInt8 aFldHeader[] =
3802 {
3803 0xFF, 0xFF, 0xFF, 0xFF, // Unicode Marker...
3804 0, 0, 0, 0,// 0, 0, 0, 0
3805 };
3806
3807 aFldHeader[4] |= (type & 0x03);
3808 sal_Int32 ffres = 0; // rFieldmark.GetFFRes();
3809 if ( pAsCheckbox && pAsCheckbox->IsChecked() )
3810 ffres = 1;
3811 else if ( type == 2 )
3812 {
3813 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pResParameter = rFieldmark.GetParameters()->find(::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN));
3814 if(pResParameter != rFieldmark.GetParameters()->end())
3815 pResParameter->second >>= ffres;
3816 else
3817 ffres = 0;
3818 }
3819 aFldHeader[4] |= ( (ffres<<2) & 0x7C );
3820
3821 std::vector< ::rtl::OUString > aListItems;
3822 if (type==2)
3823 {
3824 aFldHeader[5] |= 0x80; // ffhaslistbox
3825 const ::sw::mark::IFieldmark::parameter_map_t* const pParameters = rFieldmark.GetParameters();
3826 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_LISTENTRY));
3827 if(pListEntries != pParameters->end())
3828 {
3829 uno::Sequence< ::rtl::OUString > vListEntries;
3830 pListEntries->second >>= vListEntries;
3831 copy(::comphelper::stl_begin(vListEntries), ::comphelper::stl_end(vListEntries), back_inserter(aListItems));
3832 }
3833 }
3834
3835 const ::rtl::OUString ffdeftext;
3836 const ::rtl::OUString ffformat;
3837 const ::rtl::OUString ffhelptext;
3838 const ::rtl::OUString ffstattext;
3839 const ::rtl::OUString ffentrymcr;
3840 const ::rtl::OUString ffexitmcr;
3841
3842
3843 const sal_uInt8 aFldData[] =
3844 {
3845 0x44,0, // the start of "next" data
3846 0,0,0,0,0,0,0,0,0,0, // PIC-Structure! /10
3847 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3848 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3849 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3850 0,0,0,0, // / /4
3851 };
3852 sal_uInt32 slen = sizeof(sal_uInt32)
3853 + sizeof(aFldData)
3854 + sizeof( aFldHeader )
3855 + 2*ffname.getLength() + 4
3856 + 2*ffdeftext.getLength() + 4
3857 + 2*ffformat.getLength() + 4
3858 + 2*ffhelptext.getLength() + 4
3859 + 2*ffstattext.getLength() + 4
3860 + 2*ffentrymcr.getLength() + 4
3861 + 2*ffexitmcr.getLength() + 4;
3862 if ( type==2 ) {
3863 slen += 2; // for 0xFF, 0xFF
3864 slen += 4; // for num of list items
3865 const int items = aListItems.size();
3866 for( int i = 0; i < items; i++ ) {
3867 rtl::OUString item = aListItems[i];
3868 slen += 2 * item.getLength() + 2;
3869 }
3870 }
3871
3872 *pDataStrm << slen;
3873
3874 int len = sizeof( aFldData );
3875 OSL_ENSURE( len == 0x44-sizeof(sal_uInt32), "SwWW8Writer::WriteFormData(..) - wrong aFldData length" );
3876 pDataStrm->Write( aFldData, len );
3877
3878 len = sizeof( aFldHeader );
3879 OSL_ENSURE( len == 8, "SwWW8Writer::WriteFormData(..) - wrong aFldHeader length" );
3880
3881 pDataStrm->Write( aFldHeader, len );
3882
3883 SwWW8Writer::WriteString_xstz( *pDataStrm, ffname, true ); // Form field name
3884
3885 if ( type == 0 )
3886 SwWW8Writer::WriteString_xstz( *pDataStrm, ffdeftext, true );
3887 else
3888 pDataStrm->WriteNumber( (sal_uInt16)0 );
3889
3890 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffformat ), true );
3891 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffhelptext ), true );
3892 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffstattext ), true );
3893 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffentrymcr ), true );
3894 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffexitmcr ), true );
3895 if (type==2) {
3896 *pDataStrm<<(sal_uInt16)0xFFFF;
3897 const int items=aListItems.size();
3898 *pDataStrm<<(sal_uInt32)items;
3899 for(int i=0;i<items;i++) {
3900 rtl::OUString item=aListItems[i];
3901 SwWW8Writer::WriteString_xstz( *pDataStrm, item, false );
3902 }
3903 }
3904 }
3905
WriteHyperlinkData(const sw::mark::IFieldmark &)3906 void WW8Export::WriteHyperlinkData( const sw::mark::IFieldmark& /*rFieldmark*/ )
3907 {
3908 //@TODO implement me !!!
3909 }
3910
TableNodeInfoInner(ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner)3911 void WW8AttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
3912 {
3913 SVBT16 nStyle;
3914 ShortToSVBT16( m_rWW8Export.nStyleBeforeFly, nStyle );
3915
3916 #ifdef DEBUG
3917 ::std::clog << "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner->toString();
3918 #endif
3919
3920 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3921
3922 sal_uInt32 nShadowsBefore = pNodeInfoInner->getShadowsBefore();
3923 if (nShadowsBefore > 0)
3924 {
3925 ww8::WW8TableNodeInfoInner::Pointer_t
3926 pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
3927
3928 pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
3929 pTmpNodeInfoInner->setEndOfCell(true);
3930
3931 for (sal_uInt32 n = 0; n < nShadowsBefore; ++n)
3932 {
3933 m_rWW8Export.WriteCR(pTmpNodeInfoInner);
3934
3935 m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2,
3936 m_rWW8Export.pO->Count() ); // Style #
3937 TableInfoCell(pTmpNodeInfoInner);
3938 m_rWW8Export.pPapPlc->AppendFkpEntry
3939 ( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
3940 m_rWW8Export.pO->GetData() );
3941
3942 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3943 }
3944 }
3945
3946 if (pNodeInfoInner->isEndOfCell())
3947 {
3948 #ifdef DEBUG
3949 ::std::clog << "<endOfCell/>" << ::std::endl;
3950 #endif
3951 m_rWW8Export.WriteCR(pNodeInfoInner);
3952
3953 m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
3954 TableInfoCell(pNodeInfoInner);
3955 m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
3956 m_rWW8Export.pO->GetData() );
3957
3958 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3959 }
3960
3961 sal_uInt32 nShadowsAfter = pNodeInfoInner->getShadowsAfter();
3962 if (nShadowsAfter > 0)
3963 {
3964 ww8::WW8TableNodeInfoInner::Pointer_t
3965 pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
3966
3967 pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
3968 pTmpNodeInfoInner->setEndOfCell(true);
3969
3970 for (sal_uInt32 n = 0; n < nShadowsAfter; ++n)
3971 {
3972 m_rWW8Export.WriteCR(pTmpNodeInfoInner);
3973
3974 m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
3975 TableInfoCell(pTmpNodeInfoInner);
3976 m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
3977 m_rWW8Export.pO->GetData() );
3978
3979 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3980 }
3981 }
3982
3983 if (pNodeInfoInner->isEndOfLine())
3984 {
3985 #ifdef DEBUG
3986 ::std::clog << "<endOfLine/>" << ::std::endl;
3987 #endif
3988 TableRowEnd(pNodeInfoInner->getDepth());
3989
3990 ShortToSVBT16(0, nStyle);
3991 m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
3992 TableInfoRow(pNodeInfoInner);
3993 m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
3994 m_rWW8Export.pO->GetData() );
3995
3996 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3997 }
3998 #ifdef DEBUG
3999 ::std::clog << "</OutWW8_TableNodeInfoInner>" << ::std::endl;
4000 #endif
4001 }
4002
OutputStartNode(const SwStartNode & rNode)4003 void MSWordExportBase::OutputStartNode( const SwStartNode & rNode)
4004 {
4005 #if 0
4006 #ifdef DEBUG
4007 ::std::clog << "<OutWW8_SwStartNode>" << dbg_out(&rNode) << ::std::endl;
4008 #endif
4009 #endif
4010
4011 ww8::WW8TableNodeInfo::Pointer_t pNodeInfo =
4012 mpTableInfo->getTableNodeInfo( &rNode );
4013
4014 if (pNodeInfo.get() != NULL)
4015 {
4016 #ifdef DEBUG
4017 ::std::clog << pNodeInfo->toString() << ::std::endl;
4018 #endif
4019
4020 const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
4021 ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aIt(aInners.rbegin());
4022 ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aEnd(aInners.rend());
4023 while (aIt != aEnd)
4024 {
4025 ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
4026
4027 AttrOutput().TableNodeInfoInner(pInner);
4028 aIt++;
4029 }
4030 }
4031 #ifdef DEBUG
4032 ::std::clog << "</OutWW8_SwStartNode>" << ::std::endl;
4033 #endif
4034 }
4035
OutputEndNode(const SwEndNode & rNode)4036 void MSWordExportBase::OutputEndNode( const SwEndNode &rNode )
4037 {
4038 #ifdef DEBUG
4039 // whoever has need of the missing function should go and implement it!
4040 // This piece of code always breaks builds...
4041 // ::std::clog << "<OutWW8_SwEndNode>" << dbg_out(&rNode) << ::std::endl;
4042 #endif
4043
4044 ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = mpTableInfo->getTableNodeInfo( &rNode );
4045
4046 if (pNodeInfo.get() != NULL)
4047 {
4048 #ifdef DEBUG
4049 ::std::clog << pNodeInfo->toString() << ::std::endl;
4050 #endif
4051
4052 const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
4053 ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt(aInners.begin());
4054 ww8::WW8TableNodeInfo::Inners_t::const_iterator aEnd(aInners.end());
4055 while (aIt != aEnd)
4056 {
4057 ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
4058 AttrOutput().TableNodeInfoInner(pInner);
4059 aIt++;
4060 }
4061 }
4062 #ifdef DEBUG
4063 ::std::clog << "</OutWW8_SwEndNode>" << ::std::endl;
4064 #endif
4065 }
4066
GetNfKeywordTable()4067 const NfKeywordTable & MSWordExportBase::GetNfKeywordTable()
4068 {
4069 if (pKeyMap.get() == NULL)
4070 {
4071 pKeyMap.reset(new NfKeywordTable);
4072 NfKeywordTable & rKeywordTable = *pKeyMap;
4073 rKeywordTable[NF_KEY_D] = ::rtl::OUString::createFromAscii("d");
4074 rKeywordTable[NF_KEY_DD] = ::rtl::OUString::createFromAscii("dd");
4075 rKeywordTable[NF_KEY_DDD] = ::rtl::OUString::createFromAscii("ddd");
4076 rKeywordTable[NF_KEY_DDDD] = ::rtl::OUString::createFromAscii("dddd");
4077 rKeywordTable[NF_KEY_M] = ::rtl::OUString::createFromAscii("M");
4078 rKeywordTable[NF_KEY_MM] = ::rtl::OUString::createFromAscii("MM");
4079 rKeywordTable[NF_KEY_MMM] = ::rtl::OUString::createFromAscii("MMM");
4080 rKeywordTable[NF_KEY_MMMM] = ::rtl::OUString::createFromAscii("MMMM");
4081 rKeywordTable[NF_KEY_NN] = ::rtl::OUString::createFromAscii("ddd");
4082 rKeywordTable[NF_KEY_NNN] = ::rtl::OUString::createFromAscii("dddd");
4083 rKeywordTable[NF_KEY_NNNN] = ::rtl::OUString::createFromAscii("dddd");
4084 rKeywordTable[NF_KEY_YY] = ::rtl::OUString::createFromAscii("yy");
4085 rKeywordTable[NF_KEY_YYYY] = ::rtl::OUString::createFromAscii("yyyy");
4086 rKeywordTable[NF_KEY_H] = ::rtl::OUString::createFromAscii("H");
4087 rKeywordTable[NF_KEY_HH] = ::rtl::OUString::createFromAscii("HH");
4088 rKeywordTable[NF_KEY_MI] = ::rtl::OUString::createFromAscii("m");
4089 rKeywordTable[NF_KEY_MMI] = ::rtl::OUString::createFromAscii("mm");
4090 rKeywordTable[NF_KEY_S] = ::rtl::OUString::createFromAscii("s");
4091 rKeywordTable[NF_KEY_SS] = ::rtl::OUString::createFromAscii("ss");
4092 rKeywordTable[NF_KEY_AMPM] = ::rtl::OUString::createFromAscii("AM/PM");
4093 }
4094
4095 return *pKeyMap;
4096 }
4097
4098 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
4099