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