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