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