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