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