merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / ww8 / wrtww8.cxx
blob4e4503e484e5ba40a518848e9b7c37afcef8152f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtww8.cxx,v $
10 * $Revision: 1.91.98.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
35 #include <iostream>
37 #include <com/sun/star/embed/ElementModes.hpp>
38 #include <com/sun/star/embed/XStorage.hpp>
39 #include <unotools/ucbstreamhelper.hxx>
41 #include <algorithm>
43 #include <hintids.hxx>
44 #include <string.h> // memcpy()
45 #include <osl/endian.h>
46 #include <docsh.hxx>
48 #define _SVSTDARR_BOOLS
49 #include <svtools/svstdarr.hxx>
51 #include <svtools/fltrcfg.hxx>
52 #include <vcl/salbtype.hxx>
53 #include <sot/storage.hxx>
54 #include <svtools/zformat.hxx>
55 #include <sfx2/docinf.hxx>
56 #include <svx/tstpitem.hxx>
57 #include <svx/svdmodel.hxx>
58 #include <svx/svdpage.hxx>
59 #include <svx/hyznitem.hxx>
60 #include <svx/langitem.hxx>
61 #include <svx/msoleexp.hxx>
62 #include <svx/msocximex.hxx>
63 #include <svx/lrspitem.hxx>
64 #include <svx/boxitem.hxx>
65 #include <svx/brshitem.hxx>
66 #include <swtypes.hxx>
67 #include <swrect.hxx>
68 #include <txatbase.hxx>
69 #include <fmtcntnt.hxx>
70 #include <fmtpdsc.hxx>
71 #include <fmtrowsplt.hxx>
72 #include <frmatr.hxx>
73 #include <doc.hxx>
74 #include <docary.hxx>
75 #include <pam.hxx>
76 #include <ndtxt.hxx>
77 #include <shellio.hxx>
78 #include <docstat.hxx>
79 #include <pagedesc.hxx>
80 #include <IMark.hxx>
81 #include <swtable.hxx>
82 #include <wrtww8.hxx>
83 #include <ww8par.hxx>
84 #include <fltini.hxx>
85 #include <swmodule.hxx>
86 #include <section.hxx>
87 #include <swfltopt.hxx>
88 #include <fmtinfmt.hxx>
89 #include <txtinet.hxx>
90 #include <fmturl.hxx>
91 #include <fesh.hxx>
92 #include <svtools/imap.hxx>
93 #include <svtools/imapobj.hxx>
94 #include <tools/urlobj.hxx>
95 #include <mdiexp.hxx> // Progress
96 #include <statstr.hrc> // ResId fuer Statusleiste
97 #include <fmtline.hxx>
98 #include <fmtfsize.hxx>
99 #include <comphelper/extract.hxx>
101 #include <writerfilter/doctok/sprmids.hxx>
103 #include "writerhelper.hxx"
104 #include "writerwordglue.hxx"
105 #include "ww8attributeoutput.hxx"
107 #include <IDocumentMarkAccess.hxx>
108 #include <ecmaflds.hxx>
110 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
111 #include <com/sun/star/document/XDocumentProperties.hpp>
113 #include "dbgoutsw.hxx"
115 #include <sfx2/docfile.hxx>
116 #include <svtools/stritem.hxx>
117 #include <unotools/tempfile.hxx>
118 #include <svx/mscodec.hxx>
119 #include <osl/time.h>
120 #include <rtl/random.h>
122 using namespace sw::util;
123 using namespace sw::types;
125 /** FKP - Formatted disK Page
127 class WW8_WrFkp
129 BYTE* pFkp; // gesamter Fkp ( zuerst nur FCs und Sprms )
130 BYTE* pOfs; // Pointer auf Offset-Bereich, spaeter nach pFkp kopiert
131 ePLCFT ePlc;
132 short nStartGrp; // ab hier grpprls
133 short nOldStartGrp;
134 BYTE nItemSize;
135 BYTE nIMax; // Anzahl der Eintrags-Paare
136 BYTE nOldVarLen;
137 BYTE nMark;
138 bool bCombined; // true : Einfuegen verboten
140 BYTE SearchSameSprm( USHORT nVarLen, const BYTE* pSprms );
141 public:
142 WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8);
143 ~WW8_WrFkp();
144 bool Append( WW8_FC nEndFc, USHORT nVarLen = 0, const BYTE* pSprms = 0 );
145 bool Combine();
146 void Write( SvStream& rStrm, SwWW8WrGrf& rGrf );
148 bool IsEqualPos(WW8_FC nEndFc) const
149 { return !bCombined && nIMax && nEndFc == ((INT32*)pFkp)[nIMax]; }
150 void MergeToNew( short& rVarLen, BYTE *& pNewSprms );
151 bool IsEmptySprm() const
152 { return !bCombined && nIMax && !nOldVarLen; }
153 void SetNewEnd( WW8_FC nEnd )
154 { ((INT32*)pFkp)[nIMax] = nEnd; }
156 #ifdef __WW8_NEEDS_COPY
157 WW8_FC GetStartFc() const;
158 WW8_FC GetEndFc() const;
159 #else
160 WW8_FC GetStartFc() const { return ((INT32*)pFkp)[0]; };
161 WW8_FC GetEndFc() const { return ((INT32*)pFkp)[nIMax]; };
162 #endif // defined __WW8_NEEDS_COPY
164 BYTE *CopyLastSprms(BYTE &rLen, bool bVer8);
168 // -------------------------------------------------------------------------
169 // class WW8_WrPc sammelt alle Piece-Eintraege fuer ein Piece
170 // -------------------------------------------------------------------------
172 class WW8_WrPc
174 WW8_CP nStartCp; // Start ZeichenPosition vom Text
175 WW8_FC nStartFc; // Start File Position vom Text
176 USHORT nStatus; // Absatzende im Piece ?
178 public:
179 WW8_WrPc(WW8_FC nSFc, WW8_CP nSCp )
180 : nStartCp( nSCp ), nStartFc( nSFc ), nStatus( 0x0040 )
183 void SetStatus() { nStatus = 0x0050; }
184 USHORT GetStatus() const { return nStatus; }
185 WW8_CP GetStartCp() const { return nStartCp; }
186 WW8_FC GetStartFc() const { return nStartFc; }
189 class WW8_WrtBookmarks
191 private:
192 SvULongs aSttCps, aEndCps; // Array of Start- and End CPs
193 SvBools aFieldMarks; // If the bookmark is in a field result
194 std::vector<String> maSwBkmkNms; // Array of Sw - Bookmarknames
195 typedef std::vector<String>::iterator myIter;
197 USHORT GetPos( const String& rNm );
199 //No copying
200 WW8_WrtBookmarks(const WW8_WrtBookmarks&);
201 WW8_WrtBookmarks& operator=(const WW8_WrtBookmarks&);
202 public:
203 WW8_WrtBookmarks();
204 ~WW8_WrtBookmarks();
206 void Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark* pBkmk=NULL );
207 void Write( WW8Export& rWrt );
208 void MoveFieldMarks(ULONG nFrom,ULONG nTo);
210 // String GetWWBkmkName( const String& rName ) const;
213 #define ANZ_DEFAULT_STYLES 16
215 // die Namen der StorageStreams
216 #define sMainStream CREATE_CONST_ASC("WordDocument")
217 #define sCompObj CREATE_CONST_ASC("\1CompObj")
220 SV_IMPL_VARARR( WW8Bytes, BYTE )
221 SV_IMPL_PTRARR( WW8_WrFkpPtrs, WW8_FkpPtr )
223 typedef WW8_WrPc* WW8_WrPcPtr;
224 SV_DECL_PTRARR_DEL( WW8_WrPcPtrs, WW8_WrPcPtr, 4, 4 )
225 SV_IMPL_PTRARR( WW8_WrPcPtrs, WW8_WrPcPtr )
227 static void WriteDop( WW8Export& rWrt )
229 WW8Dop& rDop = *rWrt.pDop;
231 // i#78951#, store the value of unknown compatability options
232 rDop.SetCompatabilityOptions( rWrt.pDoc->Getn32DummyCompatabilityOptions1());
233 rDop.SetCompatabilityOptions2( rWrt.pDoc->Getn32DummyCompatabilityOptions2());
235 rDop.fNoLeading = !rWrt.pDoc->get(IDocumentSettingAccess::ADD_EXT_LEADING);
236 rDop.fUsePrinterMetrics = !rWrt.pDoc->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE);
238 // default TabStop schreiben
239 const SvxTabStopItem& rTabStop =
240 DefaultItemGet<SvxTabStopItem>(*rWrt.pDoc, RES_PARATR_TABSTOP);
241 rDop.dxaTab = (USHORT)rTabStop[0].GetTabPos();
244 // Werte aus der DocStatistik (werden aufjedenfall fuer die
245 // DocStat-Felder benoetigt!)
246 rDop.fWCFtnEdn = true; // because they are included in StarWriter
248 const SwDocStat& rDStat = rWrt.pDoc->GetDocStat();
249 rDop.cWords = rDStat.nWord;
250 rDop.cCh = rDStat.nChar;
251 rDop.cPg = static_cast< INT16 >(rDStat.nPage);
252 rDop.cParas = rDStat.nPara;
253 rDop.cLines = rDStat.nPara;
255 SwDocShell *pDocShell(rWrt.pDoc->GetDocShell());
256 DBG_ASSERT(pDocShell, "no SwDocShell");
257 uno::Reference<document::XDocumentProperties> xDocProps;
258 if (pDocShell) {
259 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
260 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
261 xDocProps = xDPS->getDocumentProperties();
262 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
265 if (!xDocProps.is()) {
266 rDop.dttmCreated = rDop.dttmRevised = rDop.dttmLastPrint = 0x45FBAC69;
267 } else {
268 ::util::DateTime uDT = xDocProps->getCreationDate();
269 Date aD(uDT.Day, uDT.Month, uDT.Year);
270 Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
271 rDop.dttmCreated = sw::ms::DateTime2DTTM(DateTime(aD,aT));
272 uDT = xDocProps->getModificationDate();
273 Date aD2(uDT.Day, uDT.Month, uDT.Year);
274 Time aT2(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
275 rDop.dttmRevised = sw::ms::DateTime2DTTM(DateTime(aD2,aT2));
276 uDT = xDocProps->getPrintDate();
277 Date aD3(uDT.Day, uDT.Month, uDT.Year);
278 Time aT3(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
279 rDop.dttmLastPrint = sw::ms::DateTime2DTTM(DateTime(aD3,aT3));
282 rDop.fProtEnabled = rWrt.pSepx ? rWrt.pSepx->DocumentIsProtected() : 0;
284 // auch damit werden die DocStat-Felder in Kopf-/Fusszeilen nicht korrekt
285 // berechnet.
286 // ( we do not have this fields! )
288 // und noch fuer die Header und Footers
289 rDop.cWordsFtnEnd = rDStat.nWord;
290 rDop.cChFtnEdn = rDStat.nChar;
291 rDop.cPgFtnEdn = (INT16)rDStat.nPage;
292 rDop.cParasFtnEdn = rDStat.nPara;
293 rDop.cLinesFtnEdn = rDStat.nPara;
295 rDop.fDontUseHTMLAutoSpacing = (rWrt.pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX) != 0);
297 rDop.fExpShRtn = !rWrt.pDoc->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK); // #i56856#
299 rDop.Write( *rWrt.pTableStrm, *rWrt.pFib );
302 const sal_Unicode *WW8DopTypography::GetJapanNotBeginLevel1()
304 static const sal_Unicode aJapanNotBeginLevel1[nMaxFollowing] =
305 //Japanese Level 1
307 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
308 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
309 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
310 0x300f, 0x3011, 0x3015, 0x309b, 0x309c, 0x309d, 0x309e, 0x30fb,
311 0x30fd, 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a,
312 0xff1b, 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65,
313 0xff9e, 0xff9f, 0xffe0
315 return &aJapanNotBeginLevel1[0];
318 const sal_Unicode *WW8DopTypography::GetJapanNotEndLevel1()
320 static const sal_Unicode aJapanNotEndLevel1[nMaxLeading] =
321 //Japanese Level 1
323 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
324 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
325 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
327 return &aJapanNotEndLevel1[0];
330 int lcl_CmpBeginEndChars( const rtl::OUString& rSWStr,
331 const sal_Unicode* pMSStr, int nMSStrByteLen )
333 nMSStrByteLen /= sizeof( sal_Unicode );
334 if( nMSStrByteLen > rSWStr.getLength() )
335 nMSStrByteLen = rSWStr.getLength()+1;
336 nMSStrByteLen *= sizeof( sal_Unicode );
338 return memcmp( rSWStr.getStr(), pMSStr, nMSStrByteLen );
342 Converts the OOo Asian Typography into a best fit match for Microsoft
343 Asian typography. This structure is actually dumped to disk within the
344 Dop Writer. Assumption is that rTypo is cleared to 0 on entry
346 void WW8Export::ExportDopTypography(WW8DopTypography &rTypo)
348 static const sal_Unicode aLangNotBegin[4][WW8DopTypography::nMaxFollowing]=
350 //Japanese Level 1
352 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
353 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
354 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
355 0x300f, 0x3011, 0x3015, 0x3041, 0x3043, 0x3045, 0x3047, 0x3049,
356 0x3063, 0x3083, 0x3085, 0x3087, 0x308e, 0x309b, 0x309c, 0x309d,
357 0x309e, 0x30a1, 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30c3, 0x30e3,
358 0x30e5, 0x30e7, 0x30ee, 0x30f5, 0x30f6, 0x30fb, 0x30fc, 0x30fd,
359 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b,
360 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65, 0xff67,
361 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
362 0xff70, 0xff9e, 0xff9f, 0xffe0
364 //Simplified Chinese
366 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
367 0x007d, 0x00a8, 0x00b7, 0x02c7, 0x02c9, 0x2015, 0x2016, 0x2019,
368 0x201d, 0x2026, 0x2236, 0x3001, 0x3002, 0x3003, 0x3005, 0x3009,
369 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x3017, 0xff01, 0xff02,
370 0xff07, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
371 0xff40, 0xff5c, 0xff5d, 0xff5e, 0xffe0
373 //Korean
375 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
376 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2032, 0x2033,
377 0x2103, 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0xff01,
378 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
379 0xff5d, 0xffe0
381 //Traditional Chinese
383 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
384 0x007d, 0x00a2, 0x00b7, 0x2013, 0x2014, 0x2019, 0x201d, 0x2022,
385 0x2025, 0x2026, 0x2027, 0x2032, 0x2574, 0x3001, 0x3002, 0x3009,
386 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x301e, 0xfe30, 0xfe31,
387 0xfe33, 0xfe34, 0xfe36, 0xfe38, 0xfe3a, 0xfe3c, 0xfe3e, 0xfe40,
388 0xfe42, 0xfe44, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55,
389 0xfe56, 0xfe57, 0xfe5a, 0xfe5c, 0xfe5e, 0xff01, 0xff09, 0xff0c,
390 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff5c, 0xff5d, 0xff64
394 static const sal_Unicode aLangNotEnd[4][WW8DopTypography::nMaxLeading] =
396 //Japanese Level 1
398 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
399 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
400 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
402 //Simplified Chinese
404 0x0028, 0x005b, 0x007b, 0x00b7, 0x2018, 0x201c, 0x3008, 0x300a,
405 0x300c, 0x300e, 0x3010, 0x3014, 0x3016, 0xff08, 0xff0e, 0xff3b,
406 0xff5b, 0xffe1, 0xffe5
408 //Korean
410 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c,
411 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04, 0xff08,
412 0xff3b, 0xff5b, 0xffe6
414 //Traditional Chinese
416 0x0028, 0x005b, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c, 0x2035,
417 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0x301d, 0xfe35,
418 0xfe37, 0xfe39, 0xfe3b, 0xfe3d, 0xfe3f, 0xfe41, 0xfe43, 0xfe59,
419 0xfe5b, 0xfe5d, 0xff08, 0xff5b
423 const i18n::ForbiddenCharacters *pForbidden = 0;
424 const i18n::ForbiddenCharacters *pUseMe = 0;
425 BYTE nUseReserved=0;
426 int nNoNeeded=0;
428 Now we have some minor difficult issues, to wit...
429 a. MicroSoft Office can only store one set of begin and end characters in
430 a given document, not one per language.
431 b. StarOffice has only a concept of one set of begin and end characters for
432 a given language, i.e. not the two levels of kinsoku in japanese
434 What is unknown as yet is if our default begin and end chars for
435 japanese, chinese tradition, chinese simplified and korean are different
436 in Word and Writer. I already suspect that they are different between
437 different version of word itself.
439 So what have come up with is to simply see if any of the four languages
440 in OOo have been changed away from OUR defaults, and if one has then
441 export that. If more than one has in the future we may hack in something
442 which examines our document properties to see which language is used the
443 most and choose that, for now we choose the first and throw an ASSERT.
446 /*Our default Japanese Level is 2, this is a special MS hack to set this*/
447 rTypo.reserved2 = 1;
449 for (rTypo.reserved1=8;rTypo.reserved1>0;rTypo.reserved1-=2)
451 if (0 != (pForbidden = pDoc->getForbiddenCharacters(rTypo.GetConvertedLang(),
452 false)))
454 int nIdx = (rTypo.reserved1-2)/2;
455 if( lcl_CmpBeginEndChars( pForbidden->endLine,
456 aLangNotEnd[ nIdx ], sizeof(aLangNotEnd[ nIdx ]) ) ||
457 lcl_CmpBeginEndChars( pForbidden->beginLine,
458 aLangNotBegin[ nIdx ], sizeof(aLangNotBegin[ nIdx ]) ) )
460 //One exception for Japanese, if it matches a level 1 we
461 //can use one extra flag for that, rather than use a custom
462 if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
464 if (
465 !lcl_CmpBeginEndChars
467 pForbidden->endLine,
468 rTypo.GetJapanNotEndLevel1(),
469 rTypo.nMaxLeading * sizeof(sal_Unicode)
472 !lcl_CmpBeginEndChars
474 pForbidden->beginLine,
475 rTypo.GetJapanNotBeginLevel1(),
476 rTypo.nMaxFollowing * sizeof(sal_Unicode)
480 rTypo.reserved2 = 0;
481 continue;
485 if (!pUseMe)
487 pUseMe = pForbidden;
488 nUseReserved = rTypo.reserved1;
489 rTypo.iLevelOfKinsoku = 2;
491 nNoNeeded++;
496 ASSERT( nNoNeeded<=1, "Example of unexportable forbidden chars" );
497 rTypo.reserved1=nUseReserved;
498 if (rTypo.iLevelOfKinsoku)
500 rTypo.cchFollowingPunct = msword_cast<sal_Int16>
501 (pUseMe->beginLine.getLength());
502 if (rTypo.cchFollowingPunct > WW8DopTypography::nMaxFollowing - 1)
503 rTypo.cchFollowingPunct = WW8DopTypography::nMaxFollowing - 1;
505 rTypo.cchLeadingPunct = msword_cast<sal_Int16>
506 (pUseMe->endLine.getLength());
507 if (rTypo.cchLeadingPunct > WW8DopTypography::nMaxLeading - 1)
508 rTypo.cchLeadingPunct = WW8DopTypography::nMaxLeading -1;
510 memcpy(rTypo.rgxchFPunct,pUseMe->beginLine.getStr(),
511 (rTypo.cchFollowingPunct+1)*2);
513 memcpy(rTypo.rgxchLPunct,pUseMe->endLine.getStr(),
514 (rTypo.cchLeadingPunct+1)*2);
517 const IDocumentSettingAccess* pIDocumentSettingAccess = GetWriter().getIDocumentSettingAccess();
519 rTypo.fKerningPunct = pIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION);
520 rTypo.iJustification = pDoc->getCharacterCompressionType();
523 // HasItem ist fuer die Zusammenfassung der Doppel-Attribute
524 // Underline / WordLineMode und Box / Shadow.
525 // Es kann nur etwas gefunden werden, wenn diese Methode innerhalb
526 // der aufgerufenen Methoden WW8_SwAttrIter::OutAttr() und
527 // WW8Export::OutputItemSet() benutzt wird.
528 const SfxPoolItem* MSWordExportBase::HasItem( USHORT nWhich ) const
530 const SfxPoolItem* pItem=0;
531 if (pISet)
533 // if write a EditEngine text, then the WhichIds are greater as
534 // ourer own Ids. So the Id have to translate from our into the
535 // EditEngine Range
536 nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
537 if (nWhich && SFX_ITEM_SET != pISet->GetItemState(nWhich, true, &pItem))
538 pItem = 0;
540 else if( pChpIter )
541 pItem = pChpIter->HasTextItem( nWhich );
542 else
544 ASSERT( !this, "Wo ist mein ItemSet / pChpIter ?" );
545 pItem = 0;
547 return pItem;
550 const SfxPoolItem& MSWordExportBase::GetItem(USHORT nWhich) const
552 const SfxPoolItem* pItem;
553 if (pISet)
555 // if write a EditEngine text, then the WhichIds are greater as
556 // ourer own Ids. So the Id have to translate from our into the
557 // EditEngine Range
558 nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
559 ASSERT(nWhich != 0, "All broken, Impossible");
560 pItem = &pISet->Get(nWhich, true);
562 else if( pChpIter )
563 pItem = &pChpIter->GetItem( nWhich );
564 else
566 ASSERT( !this, "Wo ist mein ItemSet / pChpIter ?" );
567 pItem = 0;
569 return *pItem;
572 //------------------------------------------------------------------------------
574 WW8_WrPlc1::WW8_WrPlc1( USHORT nStructSz )
575 : aPos( 16, 16 ), nStructSiz( nStructSz )
577 nDataLen = 16 * nStructSz;
578 pData = new BYTE[ nDataLen ];
581 WW8_WrPlc1::~WW8_WrPlc1()
583 delete[] pData;
586 WW8_CP WW8_WrPlc1::Prev() const
588 USHORT nLen = aPos.Count();
589 ASSERT(nLen,"Prev called on empty list");
590 return nLen ? aPos[nLen-1] : 0;
593 void WW8_WrPlc1::Append( WW8_CP nCp, const void* pNewData )
595 ULONG nInsPos = aPos.Count() * nStructSiz;
596 aPos.Insert( nCp, aPos.Count() );
597 if( nDataLen < nInsPos + nStructSiz )
599 BYTE* pNew = new BYTE[ 2 * nDataLen ];
600 memmove( pNew, pData, nDataLen );
601 delete[] pData;
602 pData = pNew;
603 nDataLen *= 2;
605 memcpy( pData + nInsPos, pNewData, nStructSiz );
608 void WW8_WrPlc1::Finish( ULONG nLastCp, ULONG nSttCp )
610 if( aPos.Count() )
612 aPos.Insert( nLastCp, aPos.Count() );
613 if( nSttCp )
614 for( USHORT n = 0; n < aPos.Count(); ++n )
615 aPos[ n ] -= nSttCp;
620 void WW8_WrPlc1::Write( SvStream& rStrm )
622 USHORT i;
623 for( i = 0; i < aPos.Count(); ++i )
624 SwWW8Writer::WriteLong( rStrm, aPos[i] );
625 if( i )
626 rStrm.Write( pData, (i-1) * nStructSiz );
629 //------------------------------------------------------------------------------
630 // Klasse WW8_WrPlcFld fuer Felder
631 //------------------------------------------------------------------------------
634 bool WW8_WrPlcFld::Write( WW8Export& rWrt )
636 if( WW8_WrPlc1::Count() <= 1 )
637 return false;
639 WW8_FC *pfc;
640 sal_Int32 *plc;
641 switch (nTxtTyp)
643 case TXT_MAINTEXT:
644 pfc = &rWrt.pFib->fcPlcffldMom;
645 plc = &rWrt.pFib->lcbPlcffldMom;
646 break;
647 case TXT_HDFT:
648 pfc = &rWrt.pFib->fcPlcffldHdr;
649 plc = &rWrt.pFib->lcbPlcffldHdr;
650 break;
652 case TXT_FTN:
653 pfc = &rWrt.pFib->fcPlcffldFtn;
654 plc = &rWrt.pFib->lcbPlcffldFtn;
655 break;
657 case TXT_EDN:
658 pfc = &rWrt.pFib->fcPlcffldEdn;
659 plc = &rWrt.pFib->lcbPlcffldEdn;
660 break;
662 case TXT_ATN:
663 pfc = &rWrt.pFib->fcPlcffldAtn;
664 plc = &rWrt.pFib->lcbPlcffldAtn;
665 break;
667 case TXT_TXTBOX:
668 pfc = &rWrt.pFib->fcPlcffldTxbx;
669 plc = &rWrt.pFib->lcbPlcffldTxbx;
670 break;
672 case TXT_HFTXTBOX:
673 pfc = &rWrt.pFib->fcPlcffldHdrTxbx;
674 plc = &rWrt.pFib->lcbPlcffldHdrTxbx;
675 break;
677 default:
678 pfc = plc = 0;
679 break;
682 if( pfc && plc )
684 ULONG nFcStart = rWrt.pTableStrm->Tell();
685 WW8_WrPlc1::Write( *rWrt.pTableStrm );
686 *pfc = nFcStart;
687 *plc = rWrt.pTableStrm->Tell() - nFcStart;
689 return true;
692 bool WW8_WrMagicTable::Write( WW8Export& rWrt )
694 if( WW8_WrPlc1::Count() <= 1 )
695 return false;
696 ULONG nFcStart = rWrt.pTableStrm->Tell();
697 WW8_WrPlc1::Write( *rWrt.pTableStrm );
698 rWrt.pFib->fcPlcfTch = nFcStart;
699 rWrt.pFib->lcbPlcfTch = rWrt.pTableStrm->Tell() - nFcStart;
700 return true;
703 void WW8_WrMagicTable::Append( WW8_CP nCp, ULONG nData)
705 SVBT32 nLittle;
707 Tell the undocumented table hack that everything between here and the last
708 table position is nontable text, don't do it if the previous position is
709 the same as this one, as that would be a region of 0 length
711 if ((!Count()) || (Prev() != nCp))
713 UInt32ToSVBT32(nData,nLittle);
714 WW8_WrPlc1::Append(nCp, nLittle);
718 //--------------------------------------------------------------------------
720 void SwWW8Writer::FillCount( SvStream& rStrm, ULONG nCount )
722 static const UINT32 aNulls[16] =
724 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 64 Byte
727 while (nCount > 64)
729 rStrm.Write( aNulls, 64 ); // in 64-Byte-Schritten
730 nCount -= 64;
732 rStrm.Write( aNulls, nCount ); // Rest ( 0 .. 64 Bytes ) schreiben
735 ULONG SwWW8Writer::FillUntil( SvStream& rStrm, ULONG nEndPos )
737 ULONG nCurPos = rStrm.Tell();
738 if( !nEndPos ) // nEndPos == 0 -> next Page
739 nEndPos = (nCurPos + 0x1ff) & ~0x1ffUL;
741 if( nEndPos > nCurPos )
742 SwWW8Writer::FillCount( rStrm, nEndPos - nCurPos );
743 #ifndef PRODUCT
744 else
745 ASSERT( nEndPos == nCurPos, "Falsches FillUntil()" );
746 #endif
747 return rStrm.Tell();
751 //--------------------------------------------------------------------------
752 /* \f */
754 WW8_WrPlcPn::WW8_WrPlcPn( WW8Export& rWr, ePLCFT ePl, WW8_FC nStartFc )
755 : rWrt(rWr), nFkpStartPage(0), ePlc(ePl), nMark(0)
757 WW8_FkpPtr pF = new WW8_WrFkp( ePlc, nStartFc, rWrt.bWrtWW8 );
758 aFkps.Insert( pF, aFkps.Count() );
761 WW8_WrPlcPn::~WW8_WrPlcPn()
763 aFkps.DeleteAndDestroy( 0, aFkps.Count() );
766 BYTE *WW8_WrPlcPn::CopyLastSprms(BYTE &rLen)
768 WW8_FkpPtr pF = aFkps.GetObject(aFkps.Count() - 1);
769 return pF->CopyLastSprms(rLen, rWrt.bWrtWW8);
772 void WW8_WrPlcPn::AppendFkpEntry(WW8_FC nEndFc,short nVarLen,const BYTE* pSprms)
774 WW8_FkpPtr pF = aFkps.GetObject( aFkps.Count() - 1 );
776 // big sprm? build the sprmPHugePapx
777 BYTE* pNewSprms = (BYTE*)pSprms;
778 BYTE aHugePapx[ 8 ];
779 if( rWrt.bWrtWW8 && PAP == ePlc && 488 < nVarLen )
781 BYTE* p = aHugePapx;
782 *p++ = *pSprms++; // set style Id
783 *p++ = *pSprms++;
784 nVarLen -= 2;
786 long nDataPos = rWrt.pDataStrm->Tell();
787 SwWW8Writer::WriteShort( *rWrt.pDataStrm, nVarLen );
788 rWrt.pDataStrm->Write( pSprms, nVarLen );
790 Set_UInt16( p, 0x6646 ); // set SprmCode
791 Set_UInt32( p, nDataPos ); // set startpos (FC) in the datastream
792 nVarLen = static_cast< short >(p - aHugePapx);
793 pSprms = pNewSprms = aHugePapx;
795 // if append at the same FC-EndPos and there are sprms, then get the old
796 // sprms and erase it; they will append now with the new sprms
797 else if( nVarLen && pF->IsEqualPos( nEndFc ))
798 pF->MergeToNew( nVarLen, pNewSprms );
799 // has the prev EndFC an empty sprm and the current is empty too, then
800 // expand only the old EndFc to the new EndFc
801 else if( !nVarLen && pF->IsEmptySprm() )
803 pF->SetNewEnd( nEndFc );
804 return ;
807 bool bOk = pF->Append(nEndFc, nVarLen, pNewSprms);
808 if( !bOk )
810 pF->Combine();
811 pF = new WW8_WrFkp( ePlc, pF->GetEndFc(), rWrt.bWrtWW8 );// Anfang neuer Fkp
812 // == Ende alter Fkp
813 aFkps.Insert( pF, aFkps.Count() );
814 if( !pF->Append( nEndFc, nVarLen, pNewSprms ) )
816 ASSERT( !this, "Sprm liess sich nicht einfuegen" );
819 if( pNewSprms != pSprms ) //Merge to new has created a new block
820 delete[] pNewSprms;
823 void WW8_WrPlcPn::WriteFkps()
825 nFkpStartPage = (USHORT) ( SwWW8Writer::FillUntil( rWrt.Strm() ) >> 9 );
827 for( USHORT i = 0; i < aFkps.Count(); i++ )
828 aFkps.GetObject( i )->Write( rWrt.Strm(), *rWrt.pGrf );
830 if( CHP == ePlc )
832 rWrt.pFib->pnChpFirst = nFkpStartPage;
833 rWrt.pFib->cpnBteChp = aFkps.Count();
835 else
837 rWrt.pFib->pnPapFirst = nFkpStartPage;
838 rWrt.pFib->cpnBtePap = aFkps.Count();
842 void WW8_WrPlcPn::WritePlc()
844 ULONG nFcStart = rWrt.pTableStrm->Tell();
845 USHORT i;
847 for( i = 0; i < aFkps.Count(); i++ )
848 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
849 aFkps.GetObject( i )->GetStartFc() );
851 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
852 aFkps.GetObject( i - 1 )->GetEndFc() );
854 // fuer jedes FKP die Page ausgeben
855 if( rWrt.bWrtWW8) // fuer WW97 Long-Ausgabe
856 for ( i = 0; i < aFkps.Count(); i++)
857 SwWW8Writer::WriteLong( *rWrt.pTableStrm, i + nFkpStartPage );
858 else // fuer WW95 Short-Ausgabe
859 for ( i = 0; i < aFkps.Count(); i++)
860 SwWW8Writer::WriteShort( *rWrt.pTableStrm, i + nFkpStartPage );
862 if( CHP == ePlc )
864 rWrt.pFib->fcPlcfbteChpx = nFcStart;
865 rWrt.pFib->lcbPlcfbteChpx = rWrt.pTableStrm->Tell() - nFcStart;
867 else
869 rWrt.pFib->fcPlcfbtePapx = nFcStart;
870 rWrt.pFib->lcbPlcfbtePapx = rWrt.pTableStrm->Tell() - nFcStart;
874 //--------------------------------------------------------------------------
875 /* \f */
877 WW8_WrFkp::WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8)
878 : ePlc(ePl), nStartGrp(511), nOldStartGrp(511),
879 nItemSize( ( CHP == ePl ) ? 1 : ( bWrtWW8 ? 13 : 7 )),
880 nIMax(0), nOldVarLen(0), nMark(0), bCombined(false)
882 pFkp = (BYTE*)new INT32[128]; // 512 Byte
883 pOfs = (BYTE*)new INT32[128]; // 512 Byte
884 memset( pFkp, 0, 4 * 128 );
885 memset( pOfs, 0, 4 * 128 );
886 ( (INT32*)pFkp )[0] = nStartFc; // 0. FC-Eintrag auf nStartFc
889 WW8_WrFkp::~WW8_WrFkp()
891 delete[] (INT32 *)pFkp;
892 delete[] (INT32 *)pOfs;
895 BYTE WW8_WrFkp::SearchSameSprm( USHORT nVarLen, const BYTE* pSprms )
897 if( 3 < nVarLen )
899 // if the sprms contained picture-references then never equal!
900 for( BYTE n = static_cast< BYTE >(nVarLen - 1); 3 < n; --n )
901 if( pSprms[ n ] == GRF_MAGIC_3 &&
902 pSprms[ n-1 ] == GRF_MAGIC_2 &&
903 pSprms[ n-2 ] == GRF_MAGIC_1 )
904 return 0;
907 short i;
908 for( i = 0; i < nIMax; i++ )
910 BYTE nStart = pOfs[i * nItemSize];
911 if( nStart )
912 { // Hat Sprms
913 const BYTE* p = pFkp + ( (USHORT)nStart << 1 );
914 if( ( CHP == ePlc
915 ? (*p++ == nVarLen)
916 : (((USHORT)*p++ << 1 ) == (( nVarLen+1) & 0xfffe)) )
917 && !memcmp( p, pSprms, nVarLen ) )
918 return nStart; // gefunden
921 return 0; // nicht gefunden
924 BYTE *WW8_WrFkp::CopyLastSprms(BYTE &rLen, bool bVer8)
926 rLen=0;
927 BYTE *pStart=0,*pRet=0;
929 if (!bCombined)
930 pStart = pOfs;
931 else
932 pStart = pFkp + ( nIMax + 1 ) * 4;
934 BYTE nStart = *(pStart + (nIMax-1) * nItemSize);
936 const BYTE* p = pFkp + ( (USHORT)nStart << 1 );
938 if (!*p && bVer8)
939 p++;
941 if (*p)
943 rLen = *p++;
944 if (PAP == ePlc)
945 rLen *= 2;
946 pRet = new BYTE[rLen];
947 memcpy(pRet,p,rLen);
949 return pRet;
952 bool WW8_WrFkp::Append( WW8_FC nEndFc, USHORT nVarLen, const BYTE* pSprms )
954 ASSERT( !nVarLen || pSprms, "Item-Pointer fehlt" );
955 ASSERT( nVarLen < ( ( ePlc == PAP ) ? 497U : 502U ), "Sprms zu lang !" );
957 if( bCombined )
959 ASSERT( !this, "Fkp::Append: Fkp is already combined" );
960 return false;
962 INT32 n = ((INT32*)pFkp)[nIMax]; // letzter Eintrag
963 if( nEndFc <= n )
965 ASSERT( nEndFc >= n, "+Fkp: FC rueckwaerts" );
966 ASSERT( !nVarLen || !pSprms || nEndFc != n,
967 "+Fkp: selber FC mehrfach benutzt" );
968 // selber FC ohne Sprm wird ohne zu mosern ignoriert.
970 return true; // ignorieren, keinen neuen Fkp anlegen
973 BYTE nOldP = ( nVarLen ) ? SearchSameSprm( nVarLen, pSprms ) : 0;
974 // Kombinieren gleicher Eintraege
975 short nOffset=0, nPos = nStartGrp;
976 if (nVarLen && !nOldP)
978 nPos = PAP == ePlc
979 ? ( 13 == nItemSize // HACK: PAP und bWrtWW8 !!
980 ? (nStartGrp & 0xFFFE ) - nVarLen - 1
981 : (nStartGrp - (((nVarLen + 1) & 0xFFFE)+1)) & 0xFFFE )
982 : ((nStartGrp - nVarLen - 1) & 0xFFFE);
983 if( nPos < 0 )
984 return false; // Passt absolut nicht
985 nOffset = nPos; // Offset merken (kann auch ungerade sein!)
986 nPos &= 0xFFFE; // Pos fuer Sprms ( gerade Pos )
989 if( (USHORT)nPos <= ( nIMax + 2U ) * 4U + ( nIMax + 1U ) * nItemSize )
990 // Passt hinter CPs und Offsets ?
991 return false; // Nein
993 ((INT32*)pFkp)[nIMax + 1] = nEndFc; // FC eintragen
995 nOldVarLen = (BYTE)nVarLen;
996 if( nVarLen && !nOldP )
997 { // echt eintragen
998 nOldStartGrp = nStartGrp;
1000 nStartGrp = nPos;
1001 pOfs[nIMax * nItemSize] = (BYTE)( nStartGrp >> 1 );
1002 // ( DatenAnfg >> 1 ) eintragen
1003 BYTE nCnt = static_cast< BYTE >(CHP == ePlc
1004 ? ( nVarLen < 256 ) ? (BYTE) nVarLen : 255
1005 : ( ( nVarLen + 1 ) >> 1 ));
1007 pFkp[ nOffset ] = nCnt; // DatenLaenge eintragen
1008 memcpy( pFkp + nOffset + 1, pSprms, nVarLen ); // Sprms speichern
1010 else
1012 // nicht echt eintragen ( keine Sprms oder Wiederholung )
1013 // DatenAnfg 0 ( keine Daten ) oder Wiederholung
1014 pOfs[nIMax * nItemSize] = nOldP;
1016 nIMax++;
1017 return true;
1020 bool WW8_WrFkp::Combine()
1022 if( bCombined )
1023 return false;
1024 if( nIMax )
1025 memcpy( pFkp + ( nIMax + 1 ) * 4, pOfs, nIMax * nItemSize );
1026 DELETEZ( pOfs );
1027 ((BYTE*)pFkp)[511] = nIMax;
1028 bCombined = true;
1030 #if defined OSL_BIGENDIAN // Hier werden nur die FCs gedreht, die
1031 USHORT i; // Sprms muessen an anderer Stelle gedreht
1032 // werden
1033 UINT32* p;
1034 for( i = 0, p = (UINT32*)pFkp; i <= nIMax; i++, p++ )
1035 *p = SWAPLONG( *p );
1036 #endif // ifdef OSL_BIGENDIAN
1038 return true;
1041 void WW8_WrFkp::Write( SvStream& rStrm, SwWW8WrGrf& rGrf )
1043 Combine(); // Falls noch nicht Combined
1045 BYTE* p; // Suche Magic fuer nPicLocFc
1046 BYTE* pEnd = pFkp + nStartGrp;
1047 for( p = pFkp + 511 - 4; p >= pEnd; p-- )
1049 if( *p != GRF_MAGIC_1 ) // Suche nach Signatur 0x12 0x34 0x56 0xXX
1050 continue;
1051 if( *(p+1) != GRF_MAGIC_2 )
1052 continue;
1053 if( *(p+2) != GRF_MAGIC_3 )
1054 continue;
1056 SVBT32 nPos; // Signatur gefunden
1057 UInt32ToSVBT32( rGrf.GetFPos(), nPos ); // FilePos der Grafik
1058 memcpy( p, nPos, 4 ); // Patche FilePos ueber Signatur
1060 rStrm.Write( pFkp, 512 );
1063 void WW8_WrFkp::MergeToNew( short& rVarLen, BYTE *& rpNewSprms )
1065 BYTE nStart = pOfs[ (nIMax-1) * nItemSize ];
1066 if( nStart )
1067 { // Hat Sprms
1068 BYTE* p = pFkp + ( (USHORT)nStart << 1 );
1070 // old and new equal? Then copy only one into the new sprms
1071 if( nOldVarLen == rVarLen && !memcmp( p+1, rpNewSprms, nOldVarLen ))
1073 BYTE* pNew = new BYTE[ nOldVarLen ];
1074 memcpy( pNew, p+1, nOldVarLen );
1075 rpNewSprms = pNew;
1077 else
1079 BYTE* pNew = new BYTE[ nOldVarLen + rVarLen ];
1080 memcpy( pNew, p+1, nOldVarLen );
1081 memcpy( pNew + nOldVarLen, rpNewSprms, rVarLen );
1083 rpNewSprms = pNew;
1084 rVarLen = rVarLen + nOldVarLen;
1086 --nIMax;
1087 // if this sprms dont used from others, remove it
1088 bool bFnd = false;
1089 for (USHORT n = 0; n < nIMax; ++n)
1091 if (nStart == pOfs[n * nItemSize])
1093 bFnd = true;
1094 break;
1097 if (!bFnd)
1099 nStartGrp = nOldStartGrp;
1100 memset( p, 0, nOldVarLen+1 );
1105 #ifdef __WW8_NEEDS_COPY
1107 WW8_FC WW8_WrFkp::GetStartFc() const
1109 // wenn bCombined, dann ist das Array ab pFkp schon Bytemaessig auf LittleEndian
1110 // umgedreht, d.h. zum Herausholen der Anfangs- und Endpositionen muss
1111 // zurueckgedreht werden.
1112 if( bCombined )
1113 return SVBT32ToUInt32( pFkp ); // 0. Element
1114 return ((INT32*)pFkp)[0];
1117 WW8_FC WW8_WrFkp::GetEndFc() const
1119 if( bCombined )
1120 return SVBT32ToUInt32( &(pFkp[nIMax*4]) ); // nIMax-tes SVBT32-Element
1121 return ((INT32*)pFkp)[nIMax];
1124 #endif // defined __WW8_NEEDS_COPY
1128 //--------------------------------------------------------------------------
1129 // Methoden fuer Piece-Table-Verwaltung
1130 //--------------------------------------------------------------------------
1132 WW8_WrPct::WW8_WrPct(WW8_FC nfcMin, bool bSaveUniCode)
1133 : pPcts(new WW8_WrPcPtrs), nOldFc(nfcMin), bIsUni(bSaveUniCode)
1135 AppendPc( nOldFc, bIsUni );
1138 WW8_WrPct::~WW8_WrPct()
1140 delete pPcts;
1143 // Piece fuellen und neues Piece erzeugen
1144 void WW8_WrPct::AppendPc(WW8_FC nStartFc, bool bIsUnicode)
1146 WW8_CP nStartCp = nStartFc - nOldFc; // Textbeginn abziehen
1147 if ( !nStartCp )
1149 if ( 0 != pPcts->Count() )
1151 ASSERT( 1 == pPcts->Count(), "Leeres Piece !!");
1152 pPcts->DeleteAndDestroy( pPcts->Count() - 1 , 1);
1156 nOldFc = nStartFc; // StartFc als alten merken
1158 if( bIsUni )
1159 nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
1162 if ( !bIsUnicode )
1164 nStartFc <<= 1; // Adresse * 2
1165 nStartFc |= 0x40000000; // Vorletztes Bit setzen fuer !Unicode
1168 if( pPcts->Count() )
1169 nStartCp += pPcts->GetObject( pPcts->Count()- 1 )->GetStartCp();
1171 WW8_WrPcPtr pPc = new WW8_WrPc( nStartFc, nStartCp );
1172 pPcts->Insert( pPc, pPcts->Count() );
1174 bIsUni = bIsUnicode;
1178 void WW8_WrPct::WritePc( WW8Export& rWrt )
1180 ULONG nPctStart;
1181 ULONG nOldPos, nEndPos;
1182 USHORT i;
1184 nPctStart = rWrt.pTableStrm->Tell(); // Beginn Piece-Table
1185 *rWrt.pTableStrm << ( char )0x02; // Statusbyte PCT
1186 nOldPos = nPctStart + 1; // Position merken
1187 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); // Laenge folgt
1188 for( i = 0; i < pPcts->Count(); ++i ) // Bereiche
1189 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
1190 pPcts->GetObject( i )->GetStartCp() );
1193 // die letzte Pos noch errechnen
1194 ULONG nStartCp = rWrt.pFib->fcMac - nOldFc;
1195 if( bIsUni )
1196 nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
1197 nStartCp += pPcts->GetObject( i-1 )->GetStartCp();
1198 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nStartCp );
1200 // Pieceverweise
1201 for ( i = 0; i < pPcts->Count(); ++i )
1203 WW8_WrPcPtr pPc = pPcts->GetObject( i );
1205 SwWW8Writer::WriteShort( *rWrt.pTableStrm, pPc->GetStatus());
1206 SwWW8Writer::WriteLong( *rWrt.pTableStrm, pPc->GetStartFc());
1207 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0); // PRM=0
1210 // Eintraege im FIB
1211 rWrt.pFib->fcClx = nPctStart;
1212 nEndPos = rWrt.pTableStrm->Tell();
1213 rWrt.pFib->lcbClx = nEndPos - nPctStart;
1215 // und noch die Laenge eintragen
1216 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nOldPos,
1217 nEndPos - nPctStart-5 );
1221 void WW8_WrPct::SetParaBreak()
1223 ASSERT( pPcts->Count(),"SetParaBreak : aPcts.Count = 0" );
1224 pPcts->GetObject( pPcts->Count() - 1)->SetStatus();
1227 WW8_CP WW8_WrPct::Fc2Cp( ULONG nFc ) const
1229 ASSERT( nFc >= (ULONG)nOldFc, "FilePos liegt vorm letzten Piece" );
1230 ASSERT( pPcts->Count(), "Fc2Cp noch kein Piece vorhanden" );
1232 nFc -= nOldFc;
1233 if( bIsUni )
1234 nFc /= 2;
1235 return nFc + pPcts->GetObject( pPcts->Count() - 1 )->GetStartCp();
1238 //--------------------------------------------------------------------------
1239 /* \f */
1241 WW8_WrtBookmarks::WW8_WrtBookmarks()
1242 : aSttCps( 0, 16 ), aEndCps( 0, 16 )
1246 WW8_WrtBookmarks::~WW8_WrtBookmarks()
1250 void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark* )
1252 USHORT nPos = GetPos( rNm );
1253 if( USHRT_MAX == nPos )
1255 // new -> insert as start position
1256 nPos = aSttCps.Count();
1257 myIter aIter = maSwBkmkNms.end();
1258 // sort by startposition
1259 // theory: write continuous -> then the new position is at end
1260 while( nPos && aSttCps[ nPos - 1 ] > ULONG( nStartCp ))
1262 --nPos;
1263 --aIter;
1266 aSttCps.Insert(nStartCp, nPos);
1267 aEndCps.Insert(nStartCp, nPos);
1268 aFieldMarks.Insert(BOOL(false), nPos);
1269 maSwBkmkNms.insert(aIter, rNm);
1271 else
1273 // old -> its the end position
1274 ASSERT( aEndCps[ nPos ] == aSttCps[ nPos ], "end position is valid" );
1276 //If this bookmark was around a field in writer, then we want to move
1277 //it to the field result in word. The end is therefore one cp
1278 //backwards from the 0x15 end mark that was inserted.
1279 if (aFieldMarks[nPos])
1280 --nStartCp;
1282 aEndCps.Replace( nStartCp, nPos );
1287 void WW8_WrtBookmarks::Write( WW8Export& rWrt )
1289 USHORT nCount = aSttCps.Count(), i;
1290 if( nCount )
1292 SvULongs aEndSortTab( 255 < nCount ? 255 : nCount, 4 );
1293 // sort then endpositions
1294 for( i = 0; i < nCount; ++i )
1296 ULONG nCP = aEndCps[ i ];
1297 USHORT nPos = i;
1298 while( nPos && aEndSortTab[ nPos - 1 ] > nCP )
1299 --nPos;
1300 aEndSortTab.Insert( nCP, nPos );
1303 // we have some bookmarks found in the document -> write them
1304 // first the Bookmark Name Stringtable
1305 rWrt.WriteAsStringTable(maSwBkmkNms, rWrt.pFib->fcSttbfbkmk,
1306 rWrt.pFib->lcbSttbfbkmk);
1308 // second the Bookmark start positions as pcf of longs
1309 SvStream& rStrm = rWrt.bWrtWW8 ? *rWrt.pTableStrm : rWrt.Strm();
1310 rWrt.pFib->fcPlcfbkf = rStrm.Tell();
1311 for( i = 0; i < nCount; ++i )
1312 SwWW8Writer::WriteLong( rStrm, aSttCps[ i ] );
1313 SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
1314 for( i = 0; i < nCount; ++i )
1316 ULONG nEndCP = aEndCps[ i ];
1317 USHORT nPos = i;
1318 if( aEndSortTab[ nPos ] > nEndCP )
1320 while( aEndSortTab[ --nPos ] != nEndCP )
1323 else if( aEndSortTab[ nPos ] < nEndCP )
1324 while( aEndSortTab[ ++nPos ] != nEndCP )
1327 SwWW8Writer::WriteLong( rStrm, nPos );
1329 rWrt.pFib->lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->fcPlcfbkf;
1331 // third the Bookmark end positions
1332 rWrt.pFib->fcPlcfbkl = rStrm.Tell();
1333 for( i = 0; i < nCount; ++i )
1334 SwWW8Writer::WriteLong( rStrm, aEndSortTab[ i ] );
1335 SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
1336 rWrt.pFib->lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->fcPlcfbkl;
1340 USHORT WW8_WrtBookmarks::GetPos( const String& rNm )
1342 USHORT nRet = USHRT_MAX, n;
1343 for (n = 0; n < aSttCps.Count(); ++n)
1344 if (rNm == maSwBkmkNms[n])
1346 nRet = n;
1347 break;
1349 return nRet;
1352 void WW8_WrtBookmarks::MoveFieldMarks(ULONG nFrom, ULONG nTo)
1354 for (USHORT nI=0;nI<aSttCps.Count();++nI)
1356 if (aSttCps[nI] == nFrom)
1358 aSttCps[nI] = nTo;
1359 if (aEndCps[nI] == nFrom)
1361 aFieldMarks[nI] = true;
1362 aEndCps[nI] = nTo;
1368 void WW8Export::AppendBookmarks( const SwTxtNode& rNd,
1369 xub_StrLen nAktPos, xub_StrLen nLen )
1371 SvPtrarr aArr( 8, 8 );
1372 USHORT nCntnt;
1373 xub_StrLen nAktEnd = nAktPos + nLen;
1374 if( GetWriter().GetBookmarks( rNd, nAktPos, nAktEnd, aArr ))
1376 ULONG nNd = rNd.GetIndex(), nSttCP = Fc2Cp( Strm().Tell() );
1377 for( USHORT n = 0; n < aArr.Count(); ++n )
1379 ::sw::mark::IMark& rBkmk = *(::sw::mark::IMark*)aArr[ n ];
1380 if(dynamic_cast< ::sw::mark::IFieldmark *>(&rBkmk))
1381 continue;
1383 const SwPosition* pPos = &rBkmk.GetMarkPos();
1384 const SwPosition* pOPos = 0;
1385 if(rBkmk.IsExpanded())
1386 pOPos = &rBkmk.GetOtherMarkPos();
1387 if( pOPos && pOPos->nNode == pPos->nNode &&
1388 pOPos->nContent < pPos->nContent )
1390 pPos = pOPos;
1391 pOPos = &rBkmk.GetMarkPos();
1394 if( !pOPos || ( nNd == pPos->nNode.GetIndex() &&
1395 ( nCntnt = pPos->nContent.GetIndex() ) >= nAktPos &&
1396 nCntnt < nAktEnd ) )
1398 ULONG nCp = nSttCP + pPos->nContent.GetIndex() - nAktPos;
1399 pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
1401 if( pOPos && nNd == pOPos->nNode.GetIndex() &&
1402 ( nCntnt = pOPos->nContent.GetIndex() ) >= nAktPos &&
1403 nCntnt < nAktEnd )
1405 ULONG nCp = nSttCP + pOPos->nContent.GetIndex() - nAktPos;
1406 pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
1412 void WW8Export::MoveFieldMarks(ULONG nFrom, ULONG nTo)
1414 pBkmks->MoveFieldMarks(nFrom, nTo);
1417 void WW8Export::AppendBookmark( const rtl::OUString& rName, bool bSkip )
1419 ULONG nSttCP = Fc2Cp( Strm().Tell() ) + ( bSkip? 1: 0 );
1420 pBkmks->Append( nSttCP, rName );
1423 void MSWordExportBase::AppendWordBookmark( const String& rName )
1425 AppendBookmark( BookmarkToWord( rName ) );
1429 //--------------------------------------------------------------------------
1430 /* \f */
1432 void WW8_WrtRedlineAuthor::Write( Writer& rWrt )
1434 WW8Export & rWW8Wrt = *(((SwWW8Writer&)rWrt).m_pExport);
1435 rWW8Wrt.WriteAsStringTable(maAuthors, rWW8Wrt.pFib->fcSttbfRMark,
1436 rWW8Wrt.pFib->lcbSttbfRMark, rWW8Wrt.bWrtWW8 ? 0 : 2);
1439 USHORT WW8Export::AddRedlineAuthor( USHORT nId )
1441 if( !pRedlAuthors )
1443 pRedlAuthors = new WW8_WrtRedlineAuthor;
1444 pRedlAuthors->AddName(CREATE_CONST_ASC("Unknown"));
1446 return pRedlAuthors->AddName( SW_MOD()->GetRedlineAuthor( nId ) );
1449 //--------------------------------------------------------------------------
1450 /* \f */
1452 void WW8Export::WriteAsStringTable(const std::vector<String>& rStrings,
1453 INT32& rfcSttbf, INT32& rlcbSttbf, USHORT nExtraLen)
1455 USHORT n, nCount = static_cast< USHORT >(rStrings.size());
1456 if( nCount )
1458 // we have some Redlines found in the document -> the
1459 // Author Name Stringtable
1460 SvStream& rStrm = bWrtWW8 ? *pTableStrm : Strm();
1461 rfcSttbf = rStrm.Tell();
1462 if( bWrtWW8 )
1464 SwWW8Writer::WriteShort( rStrm, -1 );
1465 SwWW8Writer::WriteLong( rStrm, nCount );
1466 for( n = 0; n < nCount; ++n )
1468 const String& rNm = rStrings[n];
1469 SwWW8Writer::WriteShort( rStrm, rNm.Len() );
1470 SwWW8Writer::WriteString16(rStrm, rNm, false);
1471 if( nExtraLen )
1472 SwWW8Writer::FillCount(rStrm, nExtraLen);
1475 else
1477 SwWW8Writer::WriteShort( rStrm, 0 );
1478 for( n = 0; n < nCount; ++n )
1480 const String aNm(rStrings[n].Copy(0, 255));
1481 rStrm << (BYTE)aNm.Len();
1482 SwWW8Writer::WriteString8(rStrm, aNm, false,
1483 RTL_TEXTENCODING_MS_1252);
1484 if (nExtraLen)
1485 SwWW8Writer::FillCount(rStrm, nExtraLen);
1488 rlcbSttbf = rStrm.Tell() - rfcSttbf;
1489 if( !bWrtWW8 )
1490 SwWW8Writer::WriteShort( rStrm, rfcSttbf, (USHORT)rlcbSttbf );
1494 // WriteShort() traegt an FilePos nPos den Wert nVal ein und seekt auf die
1495 // alte FilePos zurueck. Benutzt zum Nachtragen von Laengen.
1496 void SwWW8Writer::WriteShort( SvStream& rStrm, ULONG nPos, INT16 nVal )
1498 ULONG nOldPos = rStrm.Tell(); // Pos merken
1499 rStrm.Seek( nPos );
1500 SwWW8Writer::WriteShort( rStrm, nVal );
1501 rStrm.Seek( nOldPos );
1504 void SwWW8Writer::WriteLong( SvStream& rStrm, ULONG nPos, INT32 nVal )
1506 ULONG nOldPos = rStrm.Tell(); // Pos merken
1507 rStrm.Seek( nPos );
1508 SwWW8Writer::WriteLong( rStrm, nVal );
1509 rStrm.Seek( nOldPos );
1512 void SwWW8Writer::InsUInt16(ww::bytes &rO, sal_uInt16 n)
1514 SVBT16 nL;
1515 ShortToSVBT16( n, nL );
1516 rO.push_back(nL[0]);
1517 rO.push_back(nL[1]);
1520 void SwWW8Writer::InsUInt32(ww::bytes &rO, sal_uInt32 n)
1522 SVBT32 nL;
1523 UInt32ToSVBT32( n, nL );
1524 rO.push_back(nL[0]);
1525 rO.push_back(nL[1]);
1526 rO.push_back(nL[2]);
1527 rO.push_back(nL[3]);
1530 void SwWW8Writer::InsAsString16(ww::bytes &rO, const String& rStr)
1532 const sal_Unicode* pStr = rStr.GetBuffer();
1533 for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
1534 SwWW8Writer::InsUInt16( rO, *pStr );
1537 void SwWW8Writer::InsAsString8(ww::bytes &rO, const String& rStr,
1538 rtl_TextEncoding eCodeSet)
1540 ByteString sTmp(rStr, eCodeSet);
1541 const sal_Char *pStart = sTmp.GetBuffer();
1542 const sal_Char *pEnd = pStart + sTmp.Len();
1543 rO.reserve(rO.size() + sTmp.Len());
1545 std::copy(pStart, pEnd, std::inserter(rO, rO.end()));
1548 #ifdef __WW8_NEEDS_COPY
1550 void SwWW8Writer::InsUInt16( WW8Bytes& rO, UINT16 n )
1552 SVBT16 nL;
1553 ShortToSVBT16( n, nL );
1554 rO.Insert( nL, 2, rO.Count() );
1556 void SwWW8Writer::InsUInt32( WW8Bytes& rO, UINT32 n )
1558 SVBT32 nL;
1559 UInt32ToSVBT32( n, nL );
1560 rO.Insert( nL, 4, rO.Count() );
1563 #else
1565 void SwWW8Writer::InsUInt16( WW8Bytes& rO, UINT16 n )
1567 rO.Insert( (BYTE*)&n, 2, rO.Count() );
1569 void SwWW8Writer::InsUInt32( WW8Bytes& rO, UINT32 n )
1571 rO.Insert( (BYTE*)&n, 4, rO.Count() );
1574 #endif // defined __WW8_NEEDS_COPY
1576 void SwWW8Writer::InsAsString16( WW8Bytes& rO, const String& rStr )
1578 const sal_Unicode* pStr = rStr.GetBuffer();
1579 for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
1580 SwWW8Writer::InsUInt16( rO, *pStr );
1583 void SwWW8Writer::InsAsString8( WW8Bytes& rO, const String& rStr,
1584 rtl_TextEncoding eCodeSet )
1586 ByteString sTmp( rStr, eCodeSet );
1587 rO.Insert( (BYTE*)sTmp.GetBuffer(), sTmp.Len(), rO.Count() );
1590 void SwWW8Writer::WriteString16(SvStream& rStrm, const String& rStr,
1591 bool bAddZero)
1593 ww::bytes aBytes;
1594 SwWW8Writer::InsAsString16(aBytes, rStr);
1595 if (bAddZero)
1596 SwWW8Writer::InsUInt16(aBytes, 0);
1597 //vectors are guaranteed to have contiguous memory, so we can do
1598 //this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1599 if (!aBytes.empty())
1600 rStrm.Write(&aBytes[0], aBytes.size());
1603 void SwWW8Writer::WriteString_xstz(SvStream& rStrm, const String& rStr, bool bAddZero)
1605 ww::bytes aBytes;
1606 SwWW8Writer::InsUInt16(aBytes, rStr.Len());
1607 SwWW8Writer::InsAsString16(aBytes, rStr);
1608 if (bAddZero)
1609 SwWW8Writer::InsUInt16(aBytes, 0);
1610 rStrm.Write(&aBytes[0], aBytes.size());
1614 void SwWW8Writer::WriteString8(SvStream& rStrm, const String& rStr,
1615 bool bAddZero, rtl_TextEncoding eCodeSet)
1617 ww::bytes aBytes;
1618 SwWW8Writer::InsAsString8(aBytes, rStr, eCodeSet);
1619 if (bAddZero)
1620 aBytes.push_back(0);
1621 //vectors are guaranteed to have contiguous memory, so we can do
1622 ////this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1623 if (!aBytes.empty())
1624 rStrm.Write(&aBytes[0], aBytes.size());
1627 void WW8Export::WriteStringAsPara( const String& rTxt, USHORT nStyleId )
1629 if( rTxt.Len() )
1630 OutSwString( rTxt, 0, rTxt.Len(), IsUnicode(), RTL_TEXTENCODING_MS_1252 );
1631 WriteCR(); // CR danach
1633 WW8Bytes aArr( 10, 10 );
1634 SwWW8Writer::InsUInt16( aArr, nStyleId );
1635 if( bOutTable )
1636 { // Tab-Attr
1637 // sprmPFInTable
1638 if( bWrtWW8 )
1639 SwWW8Writer::InsUInt16( aArr, NS_sprm::LN_PFInTable );
1640 else
1641 aArr.Insert( 24, aArr.Count() );
1642 aArr.Insert( 1, aArr.Count() );
1645 ULONG nPos = Strm().Tell();
1646 pPapPlc->AppendFkpEntry( nPos, aArr.Count(), aArr.GetData() );
1647 pChpPlc->AppendFkpEntry( nPos );
1650 void MSWordExportBase::WriteSpecialText( ULONG nStart, ULONG nEnd, BYTE nTTyp )
1652 BYTE nOldTyp = nTxtTyp;
1653 nTxtTyp = nTTyp;
1654 SwPaM* pOldPam = pCurPam; //!! Einfaches Umsetzen des PaM ohne
1655 SwPaM* pOldEnd = pOrigPam; // Wiederherstellen muesste es auch tun
1656 bool bOldPageDescs = bOutPageDescs;
1657 bOutPageDescs = false;
1658 // bOutKF wird in WriteKF1 gemerkt / gesetzt
1659 pCurPam = Writer::NewSwPaM( *pDoc, nStart, nEnd );
1661 // Tabelle in Sonderbereichen erkennen
1662 if ( ( nStart != pCurPam->GetMark()->nNode.GetIndex() ) &&
1663 pDoc->GetNodes()[ nStart ]->IsTableNode() )
1665 pCurPam->GetMark()->nNode = nStart;
1668 pOrigPam = pCurPam;
1669 pCurPam->Exchange();
1671 WriteText();
1673 bOutPageDescs = bOldPageDescs;
1674 delete pCurPam; // Pam wieder loeschen
1675 pCurPam = pOldPam;
1676 pOrigPam = pOldEnd;
1677 nTxtTyp = nOldTyp;
1680 void WW8Export::OutSwString(const String& rStr, xub_StrLen nStt,
1681 xub_StrLen nLen, bool bUnicode, rtl_TextEncoding eChrSet)
1684 #ifdef DEBUG
1685 ::std::clog << "<OutSwString>" << ::std::endl;
1686 #endif
1688 if( nLen )
1690 if ( bUnicode != pPiece->IsUnicode() )
1691 pPiece->AppendPc ( Strm().Tell(), bUnicode );
1693 if( nStt || nLen != rStr.Len() )
1695 String sOut( rStr.Copy( nStt, nLen ) );
1697 #ifdef DEBUG
1698 ::std::clog << ::rtl::OUStringToOString(sOut, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
1699 #endif
1701 if (bUnicode)
1702 SwWW8Writer::WriteString16(Strm(), sOut, false);
1703 else
1704 SwWW8Writer::WriteString8(Strm(), sOut, false, eChrSet);
1706 else
1708 #ifdef DEBUG
1709 ::std::clog << ::rtl::OUStringToOString(rStr, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
1710 #endif
1712 if (bUnicode)
1713 SwWW8Writer::WriteString16(Strm(), rStr, false);
1714 else
1715 SwWW8Writer::WriteString8(Strm(), rStr, false, eChrSet);
1719 #ifdef DEBUG
1720 ::std::clog << "</OutSwString>" << ::std::endl;
1721 #endif
1724 void WW8Export::WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
1726 if (pTableTextNodeInfoInner.get() != NULL && pTableTextNodeInfoInner->getDepth() == 1 && pTableTextNodeInfoInner->isEndOfCell())
1727 WriteChar('\007');
1728 else
1729 WriteChar( '\015' );
1731 pPiece->SetParaBreak();
1734 void WW8Export::WriteChar( sal_Unicode c )
1736 if( pPiece->IsUnicode() )
1737 Strm() << c;
1738 else
1739 Strm() << (BYTE)c;
1742 void MSWordExportBase::SaveData( ULONG nStt, ULONG nEnd )
1744 MSWordSaveData aData;
1746 // WW8Export only stuff - zeroed here not to issue warnings
1747 aData.pOOld = NULL;
1748 aData.mpTableAtOld = NULL;
1749 aData.mnTableStdAtLenOld = 0;
1751 // Common stuff
1752 aData.pOldPam = pCurPam;
1753 aData.pOldEnd = pOrigPam;
1754 aData.pOldFlyFmt = mpParentFrame;
1755 aData.pOldPageDesc = pAktPageDesc;
1757 aData.pOldFlyOffset = pFlyOffset;
1758 aData.eOldAnchorType = eNewAnchorType;
1760 aData.bOldOutTable = bOutTable;
1761 aData.bOldIsInTable = bIsInTable;
1762 aData.bOldFlyFrmAttrs = bOutFlyFrmAttrs;
1763 aData.bOldStartTOX = bStartTOX;
1764 aData.bOldInWriteTOX = bInWriteTOX;
1766 pCurPam = Writer::NewSwPaM( *pDoc, nStt, nEnd );
1768 // Recognize tables in special cases
1769 if ( nStt != pCurPam->GetMark()->nNode.GetIndex() &&
1770 pDoc->GetNodes()[ nStt ]->IsTableNode() )
1772 pCurPam->GetMark()->nNode = nStt;
1775 pOrigPam = pCurPam;
1776 pCurPam->Exchange();
1778 bOutTable = false;
1779 // Caution: bIsInTable should not be set here
1780 bOutFlyFrmAttrs = false;
1781 // pAttrSet = 0;
1782 bStartTOX = false;
1783 bInWriteTOX = false;
1785 maSaveData.push( aData );
1788 void MSWordExportBase::RestoreData()
1790 MSWordSaveData &rData = maSaveData.top();
1792 delete pCurPam;
1793 pCurPam = rData.pOldPam;
1794 pOrigPam = rData.pOldEnd;
1796 bOutTable = rData.bOldOutTable;
1797 bIsInTable = rData.bOldIsInTable;
1798 bOutFlyFrmAttrs = rData.bOldFlyFrmAttrs;
1799 bStartTOX = rData.bOldStartTOX;
1800 bInWriteTOX = rData.bOldInWriteTOX;
1802 mpParentFrame = rData.pOldFlyFmt;
1803 pAktPageDesc = rData.pOldPageDesc;
1805 eNewAnchorType = rData.eOldAnchorType;
1806 pFlyOffset = rData.pOldFlyOffset;
1808 maSaveData.pop();
1811 void WW8Export::SaveData( ULONG nStt, ULONG nEnd )
1813 MSWordExportBase::SaveData( nStt, nEnd );
1815 MSWordSaveData &rData = maSaveData.top();
1817 if ( pO->Count() )
1819 rData.pOOld = pO;
1820 pO = new WW8Bytes( 128, 128 );
1822 else
1823 rData.pOOld = 0; // reuse pO
1825 rData.mpTableAtOld = mpTableAt;
1826 mpTableAt = NULL;
1827 rData.mnTableStdAtLenOld = mnTableStdAtLen;
1828 mnTableStdAtLen = 0;
1830 rData.bOldWriteAll = GetWriter().bWriteAll;
1831 GetWriter().bWriteAll = true;
1834 void WW8Export::RestoreData()
1836 MSWordSaveData &rData = maSaveData.top();
1838 GetWriter().bWriteAll = rData.bOldWriteAll;
1840 ASSERT( !pO->Count(), "pO is not empty in WW8Export::RestoreData()" );
1841 if ( rData.pOOld )
1843 delete pO;
1844 pO = rData.pOOld;
1847 ASSERT( !mpTableAt || !mpTableAt->Count(), "mpTableAt is not empty in WW8Export::RestoreData()" );
1848 if ( mpTableAt )
1849 delete mpTableAt;
1850 mpTableAt = rData.mpTableAtOld;
1851 mnTableStdAtLen = rData.mnTableStdAtLenOld;
1853 MSWordExportBase::RestoreData();
1856 void WW8AttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1858 sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
1860 if ( nDepth > 0 )
1862 /* Cell */
1863 m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
1864 m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
1865 m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
1866 m_rWW8Export.InsUInt32( nDepth );
1868 if ( nDepth > 1 && pTableTextNodeInfoInner->isEndOfCell() )
1870 m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
1871 m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
1876 void WW8AttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1878 sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
1880 if ( nDepth > 0 )
1882 /* Row */
1883 if ( pTableTextNodeInfoInner->isEndOfLine() )
1885 m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
1886 m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
1888 if ( nDepth == 1 )
1890 m_rWW8Export.InsUInt16( NS_sprm::LN_PFTtp );
1891 m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
1894 m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
1895 m_rWW8Export.InsUInt32( nDepth );
1897 if ( nDepth > 1 )
1899 m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
1900 m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
1901 m_rWW8Export.InsUInt16( NS_sprm::LN_PRow );
1902 m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
1905 TableDefinition( pTableTextNodeInfoInner );
1906 TableHeight( pTableTextNodeInfoInner );
1907 TableBackgrounds( pTableTextNodeInfoInner );
1908 TableDefaultBorders( pTableTextNodeInfoInner );
1909 TableCanSplit( pTableTextNodeInfoInner );
1910 TableBidi( pTableTextNodeInfoInner );
1911 TableVerticalCell( pTableTextNodeInfoInner );
1912 TableOrientation( pTableTextNodeInfoInner );
1917 static sal_uInt16 lcl_TCFlags(const SwTableBox * pBox)
1919 sal_uInt16 nFlags = 0;
1921 long nRowSpan = pBox->getRowSpan();
1923 if (nRowSpan > 1)
1924 nFlags |= (3 << 5);
1925 else if (nRowSpan < 0)
1926 nFlags |= (1 << 5);
1928 const SwFrmFmt * pFmt = pBox->GetFrmFmt();
1929 switch (pFmt->GetVertOrient().GetVertOrient())
1931 case text::VertOrientation::CENTER:
1932 nFlags |= (1 << 7);
1933 break;
1934 case text::VertOrientation::BOTTOM:
1935 nFlags |= (2 << 7);
1936 break;
1937 default:
1938 break;
1941 return nFlags;
1944 void WW8AttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1946 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
1947 const SwTableLine * pTabLine = pTabBox->GetUpper();
1948 const SwTableBoxes & rTblBoxes = pTabLine->GetTabBoxes();
1950 sal_uInt8 nBoxes = rTblBoxes.Count();
1951 for ( sal_uInt8 n = 0; n < nBoxes; n++ )
1953 const SwTableBox * pTabBox1 = rTblBoxes[n];
1954 const SwFrmFmt * pFrmFmt = pTabBox1->GetFrmFmt();
1956 if ( FRMDIR_VERT_TOP_RIGHT == m_rWW8Export.TrueFrameDirection( *pFrmFmt ) )
1958 m_rWW8Export.InsUInt16( NS_sprm::LN_TTextFlow );
1959 m_rWW8Export.pO->Insert( BYTE(n), m_rWW8Export.pO->Count() ); //start range
1960 m_rWW8Export.pO->Insert( BYTE(n + 1), m_rWW8Export.pO->Count() ); //end range
1961 m_rWW8Export.InsUInt16( 5 ); //Equals vertical writing
1966 void WW8AttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1968 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
1969 const SwTableLine * pTabLine = pTabBox->GetUpper();
1970 const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
1973 By default the row can be split in word, and now in writer we have a
1974 feature equivalent to this, Word stores 1 for fCantSplit if the row
1975 cannot be split, we set true if we can split it. An example is #i4569#
1978 const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit();
1979 BYTE nCantSplit = (!rSplittable.GetValue()) ? 1 : 0;
1980 if ( m_rWW8Export.bWrtWW8 )
1982 m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit );
1983 m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
1984 m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit90 ); // also write fCantSplit90
1986 else
1988 m_rWW8Export.pO->Insert( 185, m_rWW8Export.pO->Count() );
1990 m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
1993 void WW8AttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1995 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
1996 const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
1998 if ( m_rWW8Export.bWrtWW8 )
2000 if ( m_rWW8Export.TrueFrameDirection(*pFrmFmt) == FRMDIR_HORI_RIGHT_TOP )
2002 m_rWW8Export.InsUInt16( NS_sprm::LN_TFBiDi );
2003 m_rWW8Export.InsUInt16( 1 );
2008 void WW8AttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2010 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2011 const SwTableLine * pTabLine = pTabBox->GetUpper();
2012 const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
2014 #if 0
2015 const SwTable * pTable = pTableTextNodeInfo->getTable();
2016 bool bNewTableModel = pTable->IsNewModel();
2017 bool bFixRowHeight = false;
2018 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2019 if (! bNewModel)
2021 sal_uInt32 nBoxes = rTabBoxes.Count();
2023 for (sal_uInt32 n = 0; n < nBoxes; n++)
2025 SwTableBox * pBox1 = rTabBoxes[n];
2026 if (pBox1->getRowspan() != 1)
2028 bFixRowHeight = true;
2029 break;
2033 #endif
2035 // Zeilenhoehe ausgeben sprmTDyaRowHeight
2036 long nHeight = 0;
2037 const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
2038 if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
2040 if ( ATT_MIN_SIZE == rLSz.GetHeightSizeType() )
2041 nHeight = rLSz.GetHeight();
2042 else
2043 nHeight = -rLSz.GetHeight();
2046 if ( nHeight )
2048 if ( m_rWW8Export.bWrtWW8 )
2049 m_rWW8Export.InsUInt16( NS_sprm::LN_TDyaRowHeight );
2050 else
2051 m_rWW8Export.pO->Insert( 189, m_rWW8Export.pO->Count() );
2052 m_rWW8Export.InsUInt16( (USHORT)nHeight );
2057 void WW8AttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2059 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2061 const SwFrmFmt *pFmt = pTable->GetFrmFmt();
2062 ASSERT(pFmt,"Impossible");
2063 if (!pFmt)
2064 return;
2066 const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
2067 const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
2069 if (
2070 (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2071 text::RelOrientation::FRAME == rHori.GetRelationOrient())
2073 (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2074 text::RelOrientation::FRAME == rVert.GetRelationOrient())
2077 sal_Int16 eHOri = rHori.GetHoriOrient();
2078 switch (eHOri)
2080 case text::HoriOrientation::CENTER:
2081 case text::HoriOrientation::RIGHT:
2082 if ( m_rWW8Export.bWrtWW8 )
2083 m_rWW8Export.InsUInt16( NS_sprm::LN_TJc );
2084 else
2085 m_rWW8Export.pO->Insert( 182, m_rWW8Export.pO->Count() );
2086 m_rWW8Export.InsUInt16( text::HoriOrientation::RIGHT == eHOri ? 2 : 1 );
2087 break;
2088 default:
2089 break;
2094 void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2096 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2097 const SwTableLine * pTabLine = pTabBox->GetUpper();
2098 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2099 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2101 if ( pTable->GetRowsToRepeat() > pTableTextNodeInfoInner->getRow() )
2103 if( m_rWW8Export.bWrtWW8 )
2104 m_rWW8Export.InsUInt16( NS_sprm::LN_TTableHeader );
2105 else
2106 m_rWW8Export.pO->Insert( 186, m_rWW8Export.pO->Count() );
2107 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
2110 // number of cell written
2111 sal_uInt32 nBoxes = rTabBoxes.Count();
2112 if ( nBoxes > 32 )
2113 nBoxes = 32;
2115 // sprm header
2116 m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTable );
2117 sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
2118 m_rWW8Export.InsUInt16( nSprmSize ); // length
2120 // number of boxes
2121 m_rWW8Export.pO->Insert( static_cast<BYTE>(nBoxes), m_rWW8Export.pO->Count() );
2123 /* cellxs */
2125 ALWAYS relative when text::HoriOrientation::NONE (nPageSize + ( nPageSize / 10 )) < nTblSz,
2126 in that case the cell width's and table width's are not real. The table
2127 width is maxed and cells relative, so we need the frame (generally page)
2128 width that the table is in to work out the true widths.
2130 //const bool bNewTableModel = pTbl->IsNewModel();
2131 const SwFrmFmt *pFmt = pTable->GetFrmFmt();
2132 ASSERT(pFmt,"Impossible");
2133 if (!pFmt)
2134 return;
2136 const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
2137 const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
2139 sal_uInt16 nTblOffset = 0;
2141 if (
2142 (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2143 text::RelOrientation::FRAME == rHori.GetRelationOrient())
2145 (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2146 text::RelOrientation::FRAME == rVert.GetRelationOrient())
2149 sal_Int16 eHOri = rHori.GetHoriOrient();
2150 switch ( eHOri )
2152 case text::HoriOrientation::CENTER:
2153 case text::HoriOrientation::RIGHT:
2154 break;
2156 default:
2157 nTblOffset = rHori.GetPos();
2158 const SvxLRSpaceItem& rLRSp = pFmt->GetLRSpace();
2159 nTblOffset += rLRSp.GetLeft();
2160 break;
2164 sal_uInt32 n = 0;
2165 m_rWW8Export.InsUInt16( nTblOffset );
2167 std::vector<SwTwips> gridCols = GetGridCols( pTableTextNodeInfoInner );
2168 for ( std::vector<SwTwips>::const_iterator it = gridCols.begin(), end = gridCols.end(); it != end; ++it )
2170 m_rWW8Export.InsUInt16( static_cast<USHORT>( *it ) + nTblOffset );
2173 /* TCs */
2174 for ( n = 0; n < nBoxes; n++ )
2176 #ifdef DEBUG
2177 sal_uInt16 npOCount = m_rWW8Export.pO->Count();
2178 #endif
2180 SwTableBox * pTabBox1 = rTabBoxes[n];
2181 const SwFrmFmt & rBoxFmt = *(pTabBox1->GetFrmFmt());
2182 if ( m_rWW8Export.bWrtWW8 )
2184 sal_uInt16 nFlags = lcl_TCFlags(pTabBox1);
2185 m_rWW8Export.InsUInt16( nFlags );
2188 static BYTE aNullBytes[] = { 0x0, 0x0 };
2190 m_rWW8Export.pO->Insert( aNullBytes, 2, m_rWW8Export.pO->Count() ); // dummy
2191 m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, rBoxFmt.GetBox() ); // 8/16 Byte
2193 #ifdef DEBUG
2194 ::std::clog << "<tclength>" << m_rWW8Export.pO->Count() - npOCount << "</tclength>"
2195 << ::std::endl;
2196 #endif
2200 std::vector<SwTwips> AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2202 std::vector<SwTwips> gridCols;
2204 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2205 const SwTableLine * pTabLine = pTabBox->GetUpper();
2206 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2207 const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
2209 // number of cell written
2210 sal_uInt32 nBoxes = rTabBoxes.Count();
2211 if ( nBoxes > 32 )
2212 nBoxes = 32;
2214 const SwFrmFmt *pFmt = pTable->GetFrmFmt();
2215 ASSERT(pFmt,"Impossible");
2216 if (!pFmt)
2217 return gridCols;
2219 const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
2220 unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
2222 sal_uInt32 nPageSize = 0;
2223 bool bRelBoxSize = false;
2225 GetTablePageSize( pTableTextNodeInfoInner, nPageSize, bRelBoxSize );
2227 SwTwips nSz = 0;
2228 for ( sal_uInt32 n = 0; n < nBoxes; n++ )
2230 const SwFrmFmt* pBoxFmt = rTabBoxes[ n ]->GetFrmFmt();
2231 const SwFmtFrmSize& rLSz = pBoxFmt->GetFrmSize();
2232 nSz += rLSz.GetWidth();
2233 SwTwips nCalc = nSz;
2234 if ( bRelBoxSize )
2235 nCalc = ( nCalc * nPageSize ) / nTblSz;
2237 gridCols.push_back( nCalc );
2240 return gridCols;
2243 void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner, sal_uInt32& rPageSize, bool& rRelBoxSize )
2245 sal_uInt32 nPageSize = 0;
2247 const SwNode *pTxtNd = pTableTextNodeInfoInner->getNode( );
2248 const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
2250 const SwFrmFmt *pFmt = pTable->GetFrmFmt();
2251 ASSERT(pFmt,"Impossible");
2252 if (!pFmt)
2253 return;
2255 const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
2256 int nWidthPercent = rSize.GetWidthPercent();
2257 bool bManualAligned = pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::NONE;
2258 if ( (pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::FULL) || bManualAligned )
2259 nWidthPercent = 100;
2260 bool bRelBoxSize = nWidthPercent != 0;
2261 unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
2262 if (nTblSz > USHRT_MAX/2 && !bRelBoxSize)
2264 ASSERT(bRelBoxSize, "huge table width but not relative, suspicious");
2265 bRelBoxSize = true;
2268 if ( bRelBoxSize )
2270 Point aPt;
2271 SwRect aRect( pFmt->FindLayoutRect( false, &aPt ) );
2272 if ( aRect.IsEmpty() )
2274 // dann besorge mal die Seitenbreite ohne Raender !!
2275 const SwFrmFmt* pParentFmt =
2276 GetExport().mpParentFrame ?
2277 &(GetExport().mpParentFrame->GetFrmFmt()) :
2278 const_cast<const SwDoc *>(GetExport().pDoc)->GetPageDesc(0).GetPageFmtOfNode(*pTxtNd, false);
2279 aRect = pParentFmt->FindLayoutRect(true);
2280 if ( 0 == ( nPageSize = aRect.Width() ) )
2282 const SvxLRSpaceItem& rLR = pParentFmt->GetLRSpace();
2283 nPageSize = pParentFmt->GetFrmSize().GetWidth() - rLR.GetLeft()
2284 - rLR.GetRight();
2287 else
2289 nPageSize = aRect.Width();
2290 if ( bManualAligned )
2292 // #i37571# For manually aligned tables
2293 const SvxLRSpaceItem &rLR = pFmt->GetLRSpace();
2294 nPageSize -= (rLR.GetLeft() + rLR.GetRight());
2299 ASSERT(nWidthPercent, "Impossible");
2300 if (nWidthPercent)
2302 nPageSize *= nWidthPercent;
2303 nPageSize /= 100;
2307 rPageSize = nPageSize;
2308 rRelBoxSize = bRelBoxSize;
2311 void WW8AttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2313 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2314 const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
2316 //Set Default, just taken from the first cell of the first
2317 //row
2318 static USHORT aBorders[] =
2320 BOX_LINE_TOP, BOX_LINE_LEFT,
2321 BOX_LINE_BOTTOM, BOX_LINE_RIGHT
2324 for ( int i = 0; i < 4; ++i )
2326 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, 0xD634 );
2327 m_rWW8Export.pO->Insert( BYTE(6), m_rWW8Export.pO->Count() );
2328 m_rWW8Export.pO->Insert( BYTE(0), m_rWW8Export.pO->Count() );
2329 m_rWW8Export.pO->Insert( BYTE(1), m_rWW8Export.pO->Count() );
2330 m_rWW8Export.pO->Insert( BYTE(1 << i), m_rWW8Export.pO->Count() );
2331 m_rWW8Export.pO->Insert( BYTE(3), m_rWW8Export.pO->Count() );
2333 SwWW8Writer::InsUInt16( *m_rWW8Export.pO,
2334 pFrmFmt->GetBox().GetDistance( aBorders[i] ) );
2338 void WW8AttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2340 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2341 const SwTableLine * pTabLine = pTabBox->GetUpper();
2342 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2344 sal_uInt8 nBoxes = rTabBoxes.Count();
2345 if ( m_rWW8Export.bWrtWW8 )
2346 m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTableShd );
2347 else
2348 m_rWW8Export.pO->Insert( (BYTE)191, m_rWW8Export.pO->Count() );
2349 m_rWW8Export.pO->Insert( (BYTE)(nBoxes * 2), m_rWW8Export.pO->Count() ); // Len
2351 for ( sal_uInt8 n = 0; n < nBoxes; n++ )
2353 const SwTableBox * pBox1 = rTabBoxes[n];
2354 const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
2355 const SfxPoolItem * pI = NULL;
2356 Color aColor;
2358 if ( SFX_ITEM_ON == pFrmFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
2360 aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
2362 else
2363 aColor = COL_AUTO;
2365 WW8_SHD aShd;
2366 m_rWW8Export.TransBrush( aColor, aShd );
2367 m_rWW8Export.InsUInt16( aShd.GetValue() );
2370 if ( m_rWW8Export.bWrtWW8 )
2372 sal_uInt8 nBoxes0 = rTabBoxes.Count();
2373 if (nBoxes0 > 21)
2374 nBoxes0 = 21;
2376 m_rWW8Export.InsUInt16( NS_sprm::LN_TCellShd );
2377 m_rWW8Export.pO->Insert( static_cast<BYTE>(nBoxes0 * 10), m_rWW8Export.pO->Count() );
2379 for ( sal_uInt8 n = 0; n < nBoxes0; n++ )
2381 const SwTableBox * pBox1 = rTabBoxes[n];
2382 const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
2383 const SfxPoolItem * pI = NULL;
2384 Color aColor;
2386 if ( SFX_ITEM_ON == pFrmFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
2388 aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
2390 else
2391 aColor = COL_AUTO;
2393 WW8SHDLong aSHD;
2394 aSHD.setCvFore( 0xFF000000 );
2396 sal_uInt32 nBgColor = aColor.GetColor();
2397 if ( nBgColor == COL_AUTO )
2398 aSHD.setCvBack( 0xFF000000 );
2399 else
2400 aSHD.setCvBack( wwUtility::RGBToBGR( nBgColor ) );
2402 aSHD.Write( m_rWW8Export );
2407 void WW8Export::SectionBreaksAndFrames( const SwTxtNode& rNode )
2409 // output page/section breaks
2410 OutputSectionBreaks( rNode.GetpSwAttrSet(), rNode );
2412 // all textframes anchored as character for the winword 7- format
2413 if ( !bWrtWW8 && !bIsInTable )
2414 OutWW6FlyFrmsInCntnt( rNode );
2417 void MSWordExportBase::WriteText()
2419 #ifdef DEBUG
2420 ::std::clog << "<WriteText>" << ::std::endl;
2421 // ::std::clog << dbg_out(pCurPam->GetDoc()->GetNodes()) << ::std::endl;
2422 #endif
2424 while( pCurPam->GetPoint()->nNode < pCurPam->GetMark()->nNode ||
2425 ( pCurPam->GetPoint()->nNode == pCurPam->GetMark()->nNode &&
2426 pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex() ) )
2428 SwNode * pNd = pCurPam->GetNode();
2430 if ( pNd->IsTxtNode() )
2431 SectionBreaksAndFrames( *pNd->GetTxtNode() );
2433 // output the various types of nodes
2434 if ( pNd->IsCntntNode() )
2436 SwCntntNode* pCNd = (SwCntntNode*)pNd;
2438 const SwPageDesc* pTemp = pCNd->GetSwAttrSet().GetPageDesc().GetPageDesc();
2439 if ( pTemp )
2440 pAktPageDesc = pTemp;
2442 pCurPam->GetPoint()->nContent.Assign( pCNd, 0 );
2443 OutputContentNode( *pCNd );
2445 else if ( pNd->IsTableNode() )
2447 mpTableInfo->processSwTable( &pNd->GetTableNode()->GetTable() );
2449 else if ( pNd->IsSectionNode() && TXT_MAINTEXT == nTxtTyp )
2450 OutputSectionNode( *pNd->GetSectionNode() );
2451 else if ( TXT_MAINTEXT == nTxtTyp && pNd->IsEndNode() &&
2452 pNd->StartOfSectionNode()->IsSectionNode() )
2454 const SwSection& rSect = pNd->StartOfSectionNode()->GetSectionNode()
2455 ->GetSection();
2456 if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
2457 bStartTOX = false;
2459 SwNodeIndex aIdx( *pNd, 1 );
2460 if ( aIdx.GetNode().IsEndNode() && aIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
2462 else if ( aIdx.GetNode().IsSectionNode() )
2464 else if ( !bIsInTable ) //No sections in table
2466 ReplaceCr( (char)0xc ); // Indikator fuer Page/Section-Break
2468 const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
2469 if ( !pParentFmt )
2470 pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
2472 ULONG nRstLnNum;
2473 if ( aIdx.GetNode().IsCntntNode() )
2474 nRstLnNum = ((SwCntntNode&)aIdx.GetNode()).GetSwAttrSet().
2475 GetLineNumber().GetStartValue();
2476 else
2477 nRstLnNum = 0;
2479 AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
2482 else if ( pNd->IsEndNode() )
2484 OutputEndNode( *pNd->GetEndNode() );
2487 if ( pNd == &pNd->GetNodes().GetEndOfContent() )
2488 break;
2490 SwNode * pCurrentNode = &pCurPam->GetPoint()->nNode.GetNode();
2491 const SwNode * pNextNode = mpTableInfo->getNextNode(pCurrentNode);
2493 if (pNextNode != NULL)
2494 pCurPam->GetPoint()->nNode = SwNodeIndex(*pNextNode);
2495 else
2496 pCurPam->GetPoint()->nNode++;
2498 ULONG nPos = pCurPam->GetPoint()->nNode.GetIndex();
2499 ::SetProgressState( nPos, pCurPam->GetDoc()->GetDocShell() );
2502 #ifdef DEBUG
2503 ::std::clog << "</WriteText>" << ::std::endl;
2504 #endif
2507 void WW8Export::WriteMainText()
2509 #ifdef DEBUG
2510 ::std::clog << "<WriteMainText>" << ::std::endl;
2511 #endif
2513 pFib->fcMin = Strm().Tell();
2515 pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
2517 WriteText();
2519 if( 0 == Strm().Tell() - pFib->fcMin ) // kein Text ?
2520 WriteCR(); // dann CR ans Ende ( sonst mault WW )
2522 pFib->ccpText = Fc2Cp( Strm().Tell() );
2523 pFldMain->Finish( pFib->ccpText, 0 );
2525 // ccpText beinhaltet Ftn- und KF-Texte
2526 // deshalb wird pFib->ccpText evtl. noch geupdated
2527 // save the StyleId of the last paragraph. Because WW97 take the style
2528 // from the last CR, that will be write after footer/Header/fontnotes/
2529 // annotation usw.
2530 const SwTxtNode* pLastNd = pCurPam->GetMark()->nNode.GetNode().GetTxtNode();
2531 if( pLastNd )
2532 nLastFmtId = GetId( (SwTxtFmtColl&)pLastNd->GetAnyFmtColl() );
2534 #ifdef DEBUG
2535 ::std::clog << "</WriteMainText>" << ::std::endl;
2536 #endif
2539 void WW8Export::WriteFkpPlcUsw()
2541 if( !bWrtWW8 )
2543 static const BYTE aSpec[2] =
2545 117, 1
2548 pChpPlc->AppendFkpEntry( Strm().Tell() ); // Sepx mit fSpecial
2549 pSepx->WriteSepx( Strm() ); // Slcx.Sepx
2550 pGrf->Write(); // Grafiken
2551 pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec ), aSpec );
2553 pChpPlc->WriteFkps(); // Fkp.Chpx
2554 pPapPlc->WriteFkps(); // Fkp.Papx
2555 pStyles->OutputStylesTable(); // Styles
2556 pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
2557 pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
2558 pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
2559 pSepx->WritePlcSed( *this ); // Slcx.PlcSed
2560 pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
2561 pChpPlc->WritePlc(); // Plcx.Chpx
2562 pPapPlc->WritePlc(); // Plcx.Papx
2563 maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
2564 if( pRedlAuthors )
2565 pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2566 pFldMain->Write( *this ); // Fields ( Main Text )
2567 pFldHdFt->Write( *this ); // Fields ( Header/Footer )
2568 pFldFtn->Write( *this ); // Fields ( FootNotes )
2569 pFldEdn->Write( *this ); // Fields ( EndNotes )
2570 pFldAtn->Write( *this ); // Fields ( Annotations )
2571 pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
2572 // plcfBkmkf/plcfBkmkl
2573 WriteDop( *this ); // Document-Properties
2576 else
2578 // Grafiken in den Data-Tream
2579 pGrf->Write(); // Grafiken
2581 // Ausgabe in WordDocument-Stream
2582 pChpPlc->WriteFkps(); // Fkp.Chpx
2583 pPapPlc->WriteFkps(); // Fkp.Papx
2584 pSepx->WriteSepx( Strm() ); // Sepx
2586 // Ausagbe in Table-Stream
2587 pStyles->OutputStylesTable(); // fuer WW8 StyleTab
2588 pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
2589 pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
2590 pTxtBxs->WritePlc( *this ); // Textbox Text Plc
2591 pHFTxtBxs->WritePlc( *this ); // Head/Foot-Textbox Text Plc
2592 pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
2594 pSepx->WritePlcSed( *this ); // Slcx.PlcSed
2595 pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
2597 pChpPlc->WritePlc(); // Plcx.Chpx
2598 pPapPlc->WritePlc(); // Plcx.Papx
2600 if( pRedlAuthors )
2601 pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2602 pFldMain->Write( *this ); // Fields ( Main Text )
2603 pFldHdFt->Write( *this ); // Fields ( Header/Footer )
2604 pFldFtn->Write( *this ); // Fields ( FootNotes )
2605 pFldEdn->Write( *this ); // Fields ( EndNotes )
2606 pFldAtn->Write( *this ); // Fields ( Annotations )
2607 pFldTxtBxs->Write( *this ); // Fields ( Textboxes )
2608 pFldHFTxtBxs->Write( *this ); // Fields ( Head/Foot-Textboxes )
2610 if (pEscher || pDoc->ContainsMSVBasic())
2613 #82587# Everytime MS 2000 creates an escher stream there is always
2614 an ObjectPool dir (even if empty). It turns out that if a copy of
2615 MS 2000 is used to open a document that contains escher graphics
2616 exported from StarOffice without this empty dir then *if* that
2617 copy of MS Office has never been used to open a MSOffice document
2618 that has escher graphics (and an ObjectPool dir of course) and
2619 that copy of office has not been used to draw escher graphics then
2620 our exported graphics do not appear. Once you do open a ms
2621 document with escher graphics or draw an escher graphic with that
2622 copy of word, then all documents from staroffice that contain
2623 escher work from then on. Tricky to track down, some sort of late
2624 binding trickery in MS where solely for first time initialization
2625 the existence of an ObjectPool dir is necessary for triggering
2626 some magic. cmc
2629 #10570# Similiarly having msvbasic storage seems to also trigger
2630 creating this stream
2632 GetWriter().GetStorage().OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool),
2633 STREAM_READWRITE | STREAM_SHARE_DENYALL);
2636 // dggInfo - escher stream
2637 WriteEscher();
2639 pSdrObjs->WritePlc( *this );
2640 pHFSdrObjs->WritePlc( *this );
2641 // spamom - office drawing table
2642 // spahdr - header office drawing table
2644 pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
2645 // plcfBkmkf/plcfBkmkl
2647 WriteNumbering();
2649 RestoreMacroCmds();
2651 pMagicTable->Write( *this );
2653 pPiece->WritePc( *this ); // Piece-Table
2654 maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
2656 //Convert OOo asian typography into MS typography structure
2657 ExportDopTypography(pDop->doptypography);
2659 WriteDop( *this ); // Document-Properties
2661 Strm().Seek( 0 );
2663 pFib->Write( Strm() ); // FIB
2666 void WW8Export::StoreDoc1()
2668 bool bNeedsFinalPara = false;
2669 // Start of Text ( Mangel ueber )
2670 SwWW8Writer::FillUntil( Strm(), pFib->fcMin );
2672 WriteMainText(); // HauptText
2673 BYTE nSprmsLen;
2674 BYTE *pLastSprms = pPapPlc->CopyLastSprms(nSprmsLen);
2676 bNeedsFinalPara |= pFtn->WriteTxt( *this ); // Footnote-Text
2677 bNeedsFinalPara |= pSepx->WriteKFTxt( *this ); // K/F-Text
2678 bNeedsFinalPara |= pAtn->WriteTxt( *this ); // Annotation-Text
2679 bNeedsFinalPara |= pEdn->WriteTxt( *this ); // EndNote-Text
2681 // create the escher streams
2682 if( bWrtWW8 )
2683 CreateEscher();
2685 bNeedsFinalPara |= pTxtBxs->WriteTxt( *this ); //Textbox Text Plc
2686 bNeedsFinalPara |= pHFTxtBxs->WriteTxt( *this );//Head/Foot-Textbox Text Plc
2688 if (bNeedsFinalPara)
2690 WriteCR();
2691 pPapPlc->AppendFkpEntry(Strm().Tell(), nSprmsLen, pLastSprms);
2693 delete[] pLastSprms;
2695 pSepx->Finish( Fc2Cp( Strm().Tell() ));// Text + Ftn + HdFt als Section-Ende
2696 pMagicTable->Finish( Fc2Cp( Strm().Tell() ),0);
2698 pFib->fcMac = Strm().Tell(); // Ende aller Texte
2700 WriteFkpPlcUsw(); // FKP, PLC, .....
2703 void MSWordExportBase::AddLinkTarget(const String& rURL)
2705 if( !rURL.Len() || rURL.GetChar(0) != INET_MARK_TOKEN )
2706 return;
2708 String aURL( BookmarkToWriter( rURL.Copy( 1 ) ) );
2709 xub_StrLen nPos = aURL.SearchBackward( cMarkSeperator );
2711 if( nPos < 2 )
2712 return;
2714 String sCmp( aURL.Copy( nPos+1 ) );
2715 sCmp.EraseAllChars();
2716 if( !sCmp.Len() )
2717 return;
2719 sCmp.ToLowerAscii();
2721 if( sCmp.EqualsAscii( pMarkToOutline ) )
2723 SwPosition aPos( *pCurPam->GetPoint() );
2724 String aOutline( BookmarkToWriter(aURL.Copy( 0, nPos )) );
2725 // If we can find the outline this bookmark refers to
2726 // save the name of the bookmark and the
2727 // node index number of where it points to
2728 if( pDoc->GotoOutline( aPos, aOutline ) )
2730 ULONG nIdx = aPos.nNode.GetIndex();
2731 aPair aImplicitBookmark;
2732 aImplicitBookmark.first = aOutline;
2733 aImplicitBookmark.second = nIdx;
2734 maImplicitBookmarks.push_back(aImplicitBookmark);
2739 void MSWordExportBase::CollectOutlineBookmarks(const SwDoc &rDoc)
2741 const SwFmtINetFmt* pINetFmt;
2742 const SwTxtINetFmt* pTxtAttr;
2743 const SwTxtNode* pTxtNd;
2745 USHORT n, nMaxItems = rDoc.GetAttrPool().GetItemCount( RES_TXTATR_INETFMT );
2746 for( n = 0; n < nMaxItems; ++n )
2748 if( 0 != (pINetFmt = (SwFmtINetFmt*)rDoc.GetAttrPool().GetItem(
2749 RES_TXTATR_INETFMT, n ) ) &&
2750 0 != ( pTxtAttr = pINetFmt->GetTxtINetFmt()) &&
2751 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
2752 pTxtNd->GetNodes().IsDocNodes() )
2754 AddLinkTarget( pINetFmt->GetValue() );
2758 const SwFmtURL *pURL;
2759 nMaxItems = rDoc.GetAttrPool().GetItemCount( RES_URL );
2760 for( n = 0; n < nMaxItems; ++n )
2762 if( 0 != (pURL = (SwFmtURL*)rDoc.GetAttrPool().GetItem(
2763 RES_URL, n ) ) )
2765 AddLinkTarget( pURL->GetURL() );
2766 const ImageMap *pIMap = pURL->GetMap();
2767 if( pIMap )
2769 for( USHORT i=0; i<pIMap->GetIMapObjectCount(); i++ )
2771 const IMapObject* pObj = pIMap->GetIMapObject( i );
2772 if( pObj )
2774 AddLinkTarget( pObj->GetURL() );
2782 namespace
2784 const ULONG WW_BLOCKSIZE = 0x200;
2786 void EncryptRC4(svx::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
2788 rIn.Seek(STREAM_SEEK_TO_END);
2789 ULONG nLen = rIn.Tell();
2790 rIn.Seek(0);
2792 sal_uInt8 in[WW_BLOCKSIZE];
2793 for (ULONG nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
2795 ULONG nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
2796 rIn.Read(in, nBS);
2797 rCtx.InitCipher(nBlock);
2798 rCtx.Encode(in, nBS, in, nBS);
2799 rOut.Write(in, nBS);
2804 void MSWordExportBase::ExportDocument( bool bWriteAll )
2806 nCharFmtStart = ANZ_DEFAULT_STYLES;
2807 nFmtCollStart = nCharFmtStart + pDoc->GetCharFmts()->Count() - 1;
2809 bStyDef = bBreakBefore = bOutKF =
2810 bOutFlyFrmAttrs = bOutPageDescs = bOutTable = bOutFirstPage =
2811 bIsInTable = bOutGrf = bInWriteEscher = bStartTOX =
2812 bInWriteTOX = false;
2814 bFtnAtTxtEnd = bEndAtTxtEnd = true;
2816 mpParentFrame = 0;
2817 pFlyOffset = 0;
2818 eNewAnchorType = FLY_PAGE;
2819 nTxtTyp = TXT_MAINTEXT;
2820 // --> OD 2007-04-19 #i43447# - removed
2821 // nFlyWidth = nFlyHeight = 0;
2822 // <--
2823 nStyleBeforeFly = nLastFmtId = 0;
2824 pStyAttr = 0;
2825 pCurrentStyle = NULL;
2826 pOutFmtNode = 0;
2827 pEscher = 0;
2828 pRedlAuthors = 0;
2829 if ( aTOXArr.Count() )
2830 aTOXArr.Remove( 0, aTOXArr.Count() );
2832 if ( !pOLEExp )
2834 UINT32 nSvxMSDffOLEConvFlags = 0;
2835 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
2836 if ( pOpt->IsMath2MathType() )
2837 nSvxMSDffOLEConvFlags |= OLE_STARMATH_2_MATHTYPE;
2838 if ( pOpt->IsWriter2WinWord() )
2839 nSvxMSDffOLEConvFlags |= OLE_STARWRITER_2_WINWORD;
2840 if ( pOpt->IsCalc2Excel() )
2841 nSvxMSDffOLEConvFlags |= OLE_STARCALC_2_EXCEL;
2842 if ( pOpt->IsImpress2PowerPoint() )
2843 nSvxMSDffOLEConvFlags |= OLE_STARIMPRESS_2_POWERPOINT;
2845 pOLEExp = new SvxMSExportOLEObjects( nSvxMSDffOLEConvFlags );
2848 if ( !pOleMap)
2849 pOleMap = new WW8OleMaps;
2851 if ( !pOCXExp )
2852 pOCXExp = new SwMSConvertControls( pDoc->GetDocShell(), pCurPam );
2854 // --> OD 2007-10-08 #i81405#
2855 // Collect anchored objects before changing the redline mode.
2856 maFrames = GetFrames( *pDoc, bWriteAll? NULL : pOrigPam );
2857 // <--
2859 mnRedlineMode = pDoc->GetRedlineMode();
2860 if ( pDoc->GetRedlineTbl().Count() )
2862 pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode | nsRedlineMode_t::REDLINE_SHOW_DELETE |
2863 nsRedlineMode_t::REDLINE_SHOW_INSERT) );
2866 maFontHelper.InitFontTable( HackIsWW8OrHigher(), *pDoc );
2867 GatherChapterFields();
2869 CollectOutlineBookmarks(*pDoc);
2871 // make unique OrdNums (Z-Order) for all drawing-/fly Objects
2872 if ( pDoc->GetDrawModel() )
2873 pDoc->GetDrawModel()->GetPage( 0 )->RecalcObjOrdNums();
2875 ExportDocument_Impl();
2877 if ( mnRedlineMode != pDoc->GetRedlineMode() )
2878 pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode) );
2881 String SwWW8Writer::GetPassword()
2883 String sUniPassword;
2884 if ( mpMedium )
2886 SfxItemSet* pSet = mpMedium->GetItemSet();
2888 const SfxPoolItem* pPasswordItem = NULL;
2889 if ( pSet && SFX_ITEM_SET == pSet->GetItemState( SID_PASSWORD, sal_True, &pPasswordItem ) )
2890 if( pPasswordItem != NULL )
2891 sUniPassword = ( (const SfxStringItem*)pPasswordItem )->GetValue();
2894 return sUniPassword;
2897 void WW8Export::ExportDocument_Impl()
2899 PrepareStorage();
2901 pFib = new WW8Fib( bWrtWW8 ? 8 : 6 );
2903 SvStream* pOldStrm = &(Strm()); // JP 19.05.99: wozu das ???
2904 SvStorageStreamRef xWwStrm( GetWriter().GetStorage().OpenSotStream( aMainStg ) );
2905 SvStorageStreamRef xTableStrm( xWwStrm ), xDataStrm( xWwStrm );
2906 xWwStrm->SetBufferSize( 32768 );
2908 if( bWrtWW8 )
2910 pFib->fWhichTblStm = 1;
2911 xTableStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::a1Table),
2912 STREAM_STD_WRITE );
2913 xDataStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::aData),
2914 STREAM_STD_WRITE );
2916 xDataStrm->SetBufferSize( 32768 ); // fuer Grafiken
2917 xTableStrm->SetBufferSize( 16384 ); // fuer die Font-/Style-Table, usw.
2919 xTableStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
2920 xDataStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
2923 GetWriter().SetStrm( *xWwStrm );
2924 pTableStrm = &xTableStrm;
2925 pDataStrm = &xDataStrm;
2927 Strm().SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
2929 String sUniPassword( GetWriter().GetPassword() );
2931 utl::TempFile aTempMain;
2932 aTempMain.EnableKillingFile();
2933 utl::TempFile aTempTable;
2934 aTempTable.EnableKillingFile();
2935 utl::TempFile aTempData;
2936 aTempData.EnableKillingFile();
2938 bool bEncrypt = false;
2940 xub_StrLen nLen = sUniPassword.Len();
2941 if ( nLen > 0 && nLen <= 15) // Password has been set
2943 bEncrypt =true;
2945 GetWriter().SetStrm( *aTempMain.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE ) );
2947 pTableStrm = aTempTable.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
2949 pDataStrm = aTempData.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
2951 sal_uInt8 aRC4EncryptionHeader[ 52 ] = {0};
2952 pTableStrm->Write( aRC4EncryptionHeader, 52 );
2955 // Default: "Standard"
2956 pSepx = new WW8_WrPlcSepx( *this ); // Sections/headers/footers
2958 pFtn = new WW8_WrPlcFtnEdn( TXT_FTN ); // Footnotes
2959 pEdn = new WW8_WrPlcFtnEdn( TXT_EDN ); // Endnotes
2960 pAtn = new WW8_WrPlcPostIt; // PostIts
2961 pTxtBxs = new WW8_WrPlcTxtBoxes( TXT_TXTBOX );
2962 pHFTxtBxs = new WW8_WrPlcTxtBoxes( TXT_HFTXTBOX );
2964 pSdrObjs = new MainTxtPlcDrawObj; // Draw-/Fly-Objects for main text
2965 pHFSdrObjs = new HdFtPlcDrawObj; // Draw-/Fly-Objects for header/footer
2967 pBkmks = new WW8_WrtBookmarks; // Bookmarks
2968 GetWriter().CreateBookmarkTbl();
2970 pPapPlc = new WW8_WrPlcPn( *this, PAP, pFib->fcMin );
2971 pChpPlc = new WW8_WrPlcPn( *this, CHP, pFib->fcMin );
2972 pO = new WW8Bytes( 128, 128 );
2973 pStyles = new MSWordStyles( *this );
2974 pFldMain = new WW8_WrPlcFld( 2, TXT_MAINTEXT );
2975 pFldHdFt = new WW8_WrPlcFld( 2, TXT_HDFT );
2976 pFldFtn = new WW8_WrPlcFld( 2, TXT_FTN );
2977 pFldEdn = new WW8_WrPlcFld( 2, TXT_EDN );
2978 pFldAtn = new WW8_WrPlcFld( 2, TXT_ATN );
2979 pFldTxtBxs = new WW8_WrPlcFld( 2, TXT_TXTBOX );
2980 pFldHFTxtBxs = new WW8_WrPlcFld( 2, TXT_HFTXTBOX );
2982 pMagicTable = new WW8_WrMagicTable;
2984 pGrf = new SwWW8WrGrf( *this );
2985 pPiece = new WW8_WrPct( pFib->fcMin, bWrtWW8 );
2986 pDop = new WW8Dop;
2989 pDop->fRevMarking = 0 != ( nsRedlineMode_t::REDLINE_ON & mnRedlineMode );
2990 pDop->fRMView = 0 != ( nsRedlineMode_t::REDLINE_SHOW_DELETE & mnRedlineMode );
2991 pDop->fRMPrint = pDop->fRMView;
2993 // set AutoHyphenation flag if found in default para style
2994 const SfxPoolItem* pItem;
2995 SwTxtFmtColl* pStdTxtFmtColl =
2996 pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false);
2997 if (pStdTxtFmtColl && SFX_ITEM_SET == pStdTxtFmtColl->GetItemState(
2998 RES_PARATR_HYPHENZONE, false, &pItem))
3000 pDop->fAutoHyphen = ((const SvxHyphenZoneItem*)pItem)->IsHyphen();
3003 StoreDoc1();
3005 if ( bEncrypt )
3007 // Generate random number with a seed of time as salt.
3008 TimeValue aTime;
3009 osl_getSystemTime( &aTime );
3010 rtlRandomPool aRandomPool = rtl_random_createPool ();
3011 rtl_random_addBytes ( aRandomPool, &aTime, 8 );
3013 sal_uInt8 aDocId[ 16 ] = {0};
3014 rtl_random_getBytes( aRandomPool, aDocId, 16 );
3016 rtl_random_destroyPool( aRandomPool );
3018 sal_Unicode aPassword[16] = {0};
3019 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
3020 aPassword[nChar] = sUniPassword.GetChar(nChar);
3022 svx::MSCodec_Std97 aCtx;
3023 aCtx.InitKey(aPassword, aDocId);
3025 SvStream *pStrmTemp, *pTableStrmTemp, *pDataStrmTemp;
3026 pStrmTemp = &xWwStrm;
3027 pTableStrmTemp = &xTableStrm;
3028 pDataStrmTemp = &xDataStrm;
3030 if ( pDataStrmTemp && pDataStrmTemp != pStrmTemp)
3031 EncryptRC4(aCtx, *pDataStrm, *pDataStrmTemp);
3033 EncryptRC4(aCtx, *pTableStrm, *pTableStrmTemp);
3035 // Write Unencrypted Header 52 bytes to the start of the table stream
3036 // EncryptionVersionInfo (4 bytes): A Version structure where Version.vMajor MUST be 0x0001, and Version.vMinor MUST be 0x0001.
3037 pTableStrmTemp->Seek( 0 );
3038 sal_uInt32 nEncType = 0x10001;
3039 *pTableStrmTemp << nEncType;
3041 sal_uInt8 pSaltData[16] = {0};
3042 sal_uInt8 pSaltDigest[16] = {0};
3043 aCtx.GetEncryptKey( aDocId, pSaltData, pSaltDigest );
3045 pTableStrmTemp->Write( aDocId, 16 );
3046 pTableStrmTemp->Write( pSaltData, 16 );
3047 pTableStrmTemp->Write( pSaltDigest, 16 );
3049 EncryptRC4(aCtx, GetWriter().Strm(), *pStrmTemp);
3051 // Write Unencrypted Fib 68 bytes to the start of the workdocument stream
3052 pFib->fEncrypted = 1; // fEncrypted indicates the document is encrypted.
3053 pFib->fObfuscated = 0; // Must be 0 for RC4.
3054 pFib->nHash = 0x34; // encrypt header bytes count of table stream.
3055 pFib->nKey = 0; // lkey2 must be 0 for RC4.
3057 pStrmTemp->Seek( 0 );
3058 pFib->WriteHeader( *pStrmTemp );
3061 if (pUsedNumTbl) // all used NumRules
3063 // clear the part of the list array that was copied from the document
3064 // - it's an auto delete array, so the rest of the array which are
3065 // duplicated lists that were added during the export will be deleted.
3066 pUsedNumTbl->Remove(0, pUsedNumTbl->Count()-nUniqueList);
3067 delete pUsedNumTbl;
3070 DELETEZ( pGrf );
3071 DELETEZ( pMagicTable );
3072 DELETEZ( pFldFtn );
3073 DELETEZ( pFldTxtBxs );
3074 DELETEZ( pFldHFTxtBxs );
3075 DELETEZ( pFldAtn );
3076 DELETEZ( pFldEdn );
3077 DELETEZ( pFldHdFt );
3078 DELETEZ( pFldMain );
3079 DELETEZ( pStyles );
3080 DELETEZ( pO );
3081 DELETEZ( pChpPlc );
3082 DELETEZ( pPapPlc );
3083 DELETEZ( pSepx );
3085 delete pRedlAuthors;
3086 delete pSdrObjs;
3087 delete pHFSdrObjs;
3088 delete pTxtBxs;
3089 delete pHFTxtBxs;
3090 delete pAtn;
3091 delete pEdn;
3092 delete pFtn;
3093 delete pBkmks;
3094 delete pPiece;
3095 delete pDop;
3096 delete pFib;
3097 GetWriter().SetStrm( *pOldStrm );
3100 xWwStrm->SetBufferSize( 0 );
3101 if( bWrtWW8 )
3103 xTableStrm->SetBufferSize( 0 );
3104 xDataStrm->SetBufferSize( 0 );
3105 if( 0 == pDataStrm->Seek( STREAM_SEEK_TO_END ))
3107 xDataStrm.Clear();
3108 pDataStrm = 0;
3109 GetWriter().GetStorage().Remove(CREATE_CONST_ASC(SL::aData));
3115 void WW8Export::PrepareStorage()
3117 ULONG nLen;
3118 const BYTE* pData;
3119 const char* pName;
3120 UINT32 nId1;
3122 if (bWrtWW8)
3124 static const char aUserName[] = "Microsoft Word-Document";
3125 static const BYTE aCompObj[] =
3127 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3128 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x09, 0x02, 0x00,
3129 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3130 0x00, 0x00, 0x00, 0x46, 0x18, 0x00, 0x00, 0x00,
3131 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
3132 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x2D, 0x44,
3133 0x6F, 0x6B, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x00,
3134 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x53, 0x57, 0x6F,
3135 0x72, 0x64, 0x44, 0x6F, 0x63, 0x00, 0x10, 0x00,
3136 0x00, 0x00, 0x57, 0x6F, 0x72, 0x64, 0x2E, 0x44,
3137 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E,
3138 0x38, 0x00, 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00,
3139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3140 0x00, 0x00
3143 pName = aUserName;
3144 pData = aCompObj;
3145 nLen = sizeof( aCompObj );
3146 nId1 = 0x00020906L;
3148 else
3150 static const char aUserName[] = "Microsoft Word 6.0 Document";
3151 static const BYTE aCompObj[] =
3153 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3154 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x09, 0x02, 0x00,
3155 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3156 0x00, 0x00, 0x00, 0x46, 0x1C, 0x00, 0x00, 0x00,
3157 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
3158 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x20, 0x36,
3159 0x2E, 0x30, 0x2D, 0x44, 0x6F, 0x6B, 0x75, 0x6D,
3160 0x65, 0x6E, 0x74, 0x00, 0x0A, 0x00, 0x00, 0x00,
3161 0x4D, 0x53, 0x57, 0x6F, 0x72, 0x64, 0x44, 0x6F,
3162 0x63, 0x00, 0x10, 0x00, 0x00, 0x00, 0x57, 0x6F,
3163 0x72, 0x64, 0x2E, 0x44, 0x6F, 0x63, 0x75, 0x6D,
3164 0x65, 0x6E, 0x74, 0x2E, 0x36, 0x00, 0x00, 0x00,
3165 0x00, 0x00
3168 pName = aUserName;
3169 pData = aCompObj;
3170 nLen = sizeof( aCompObj );
3171 nId1 = 0x00020900L;
3174 SvGlobalName aGName( nId1, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00,
3175 0x00, 0x00, 0x00, 0x46 );
3176 GetWriter().GetStorage().SetClass( aGName, 0, String::CreateFromAscii( pName ));
3177 SvStorageStreamRef xStor( GetWriter().GetStorage().OpenSotStream(sCompObj) );
3178 xStor->Write( pData, nLen );
3180 SwDocShell* pDocShell = pDoc->GetDocShell ();
3181 DBG_ASSERT(pDocShell, "no SwDocShell");
3183 if (pDocShell) {
3184 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3185 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
3186 uno::Reference<document::XDocumentProperties> xDocProps(
3187 xDPS->getDocumentProperties());
3188 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
3190 if (xDocProps.is())
3192 if ( SvtFilterOptions::Get()->IsEnableWordPreview() )
3194 ::boost::shared_ptr<GDIMetaFile> pMetaFile =
3195 pDocShell->GetPreviewMetaFile (sal_False);
3196 uno::Sequence<sal_uInt8> metaFile(
3197 sfx2::convertMetaFile(pMetaFile.get()));
3198 sfx2::SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
3200 else
3201 sfx2::SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
3206 ULONG SwWW8Writer::WriteStorage()
3208 // #i34818# #120099# - update layout (if present), for SwWriteTable
3209 ViewShell* pViewShell = NULL;
3210 pDoc->GetEditShell( &pViewShell );
3211 if( pViewShell != NULL )
3212 pViewShell->CalcLayout();
3214 long nMaxNode = pDoc->GetNodes().Count();
3215 ::StartProgress( STR_STATSTR_W4WWRITE, 0, nMaxNode, pDoc->GetDocShell() );
3217 // Tabelle am Doc.-Anfang beachten
3219 SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode();
3220 if( pTNd && bWriteAll )
3221 // mit dem TabellenNode anfangen !!
3222 pCurPam->GetPoint()->nNode = *pTNd;
3225 // Do the actual export
3227 WW8Export aExport( this, pDoc, pCurPam, pOrigPam, m_bWrtWW8 );
3228 m_pExport = &aExport;
3229 aExport.ExportDocument( bWriteAll );
3230 m_pExport = NULL;
3233 ::EndProgress( pDoc->GetDocShell() );
3234 return 0;
3237 ULONG SwWW8Writer::WriteMedium( SfxMedium& )
3239 return WriteStorage();
3242 ULONG SwWW8Writer::Write( SwPaM& rPaM, SfxMedium& rMed,
3243 const String* pFileName )
3245 mpMedium = &rMed;
3246 ULONG nRet = StgWriter::Write( rPaM, rMed, pFileName );
3247 mpMedium = NULL;
3248 return nRet;
3251 MSWordExportBase::MSWordExportBase( SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
3252 : aMainStg(sMainStream), pISet(0), pUsedNumTbl(0), mpTopNodeOfHdFtPage(0),
3253 pBmpPal(0), pKeyMap(0), pOLEExp(0), pOCXExp(0), pOleMap(0),
3254 mpTableInfo(new ww8::WW8TableInfo()), nUniqueList(0),
3255 mnHdFtIndex(0), pAktPageDesc(0), pPapPlc(0), pChpPlc(0), pChpIter(0),
3256 pStyles( NULL ),
3257 bHasHdr(false), bHasFtr(false),
3258 pDoc( pDocument ),
3259 pCurPam( pCurrentPam ),
3260 pOrigPam( pOriginalPam )
3264 MSWordExportBase::~MSWordExportBase()
3266 delete pBmpPal;
3267 if (pKeyMap)
3268 delete[] (NfKeywordTable*)pKeyMap;
3269 delete pOLEExp;
3270 delete pOCXExp;
3271 delete pOleMap;
3274 WW8Export::WW8Export( SwWW8Writer *pWriter,
3275 SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam,
3276 bool bIsWW8 )
3277 : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
3278 pO( NULL ),
3279 mpTableAt( NULL ),
3280 mnTableStdAtLen( 0 ),
3281 pSepx( NULL ),
3282 bWrtWW8( bIsWW8 ),
3283 m_pWriter( pWriter ),
3284 m_pAttrOutput( new WW8AttributeOutput( *this ) )
3288 WW8Export::~WW8Export()
3290 delete m_pAttrOutput, m_pAttrOutput = NULL;
3293 AttributeOutputBase& WW8Export::AttrOutput() const
3295 return *m_pAttrOutput;
3298 MSWordSections& WW8Export::Sections() const
3300 return *pSepx;
3303 SwWW8Writer::SwWW8Writer(const String& rFltName, const String& rBaseURL)
3304 : StgWriter(),
3305 m_bWrtWW8( rFltName.EqualsAscii( FILTER_WW8 ) ),
3306 m_pExport( NULL ),
3307 mpMedium( 0 )
3309 SetBaseURL( rBaseURL );
3312 SwWW8Writer::~SwWW8Writer()
3316 extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportDOC( const String& rFltName, const String& rBaseURL, WriterRef& xRet )
3318 xRet = new SwWW8Writer( rFltName, rBaseURL );
3321 bool WW8_WrPlcFtnEdn::WriteTxt( WW8Export& rWrt )
3323 bool bRet = false;
3324 if (TXT_FTN == nTyp)
3326 bRet = WriteGenericTxt( rWrt, TXT_FTN, rWrt.pFib->ccpFtn );
3327 rWrt.pFldFtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3328 rWrt.pFib->ccpText );
3330 else
3332 bRet = WriteGenericTxt( rWrt, TXT_EDN, rWrt.pFib->ccpEdn );
3333 rWrt.pFldEdn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3334 rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
3335 + rWrt.pFib->ccpHdr + rWrt.pFib->ccpAtn );
3337 return bRet;
3340 void WW8_WrPlcFtnEdn::WritePlc( WW8Export& rWrt ) const
3342 if( TXT_FTN == nTyp )
3344 WriteGenericPlc( rWrt, TXT_FTN, rWrt.pFib->fcPlcffndTxt,
3345 rWrt.pFib->lcbPlcffndTxt, rWrt.pFib->fcPlcffndRef,
3346 rWrt.pFib->lcbPlcffndRef );
3348 else
3350 WriteGenericPlc( rWrt, TXT_EDN, rWrt.pFib->fcPlcfendTxt,
3351 rWrt.pFib->lcbPlcfendTxt, rWrt.pFib->fcPlcfendRef,
3352 rWrt.pFib->lcbPlcfendRef );
3357 bool WW8_WrPlcPostIt::WriteTxt( WW8Export& rWrt )
3359 bool bRet = WriteGenericTxt( rWrt, TXT_ATN, rWrt.pFib->ccpAtn );
3360 rWrt.pFldAtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3361 rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
3362 + rWrt.pFib->ccpHdr );
3363 return bRet;
3366 void WW8_WrPlcPostIt::WritePlc( WW8Export& rWrt ) const
3368 WriteGenericPlc( rWrt, TXT_ATN, rWrt.pFib->fcPlcfandTxt,
3369 rWrt.pFib->lcbPlcfandTxt, rWrt.pFib->fcPlcfandRef,
3370 rWrt.pFib->lcbPlcfandRef );
3373 void WW8_WrPlcTxtBoxes::WritePlc( WW8Export& rWrt ) const
3375 if( TXT_TXTBOX == nTyp )
3377 WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcftxbxBkd,
3378 rWrt.pFib->lcbPlcftxbxBkd, rWrt.pFib->fcPlcftxbxTxt,
3379 rWrt.pFib->lcbPlcftxbxTxt );
3381 else
3383 WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcfHdrtxbxBkd,
3384 rWrt.pFib->lcbPlcfHdrtxbxBkd, rWrt.pFib->fcPlcfHdrtxbxTxt,
3385 rWrt.pFib->lcbPlcfHdrtxbxTxt );
3389 void WW8Export::RestoreMacroCmds()
3391 pFib->fcCmds = pTableStrm->Tell();
3393 uno::Reference < embed::XStorage > xSrcRoot(pDoc->GetDocShell()->GetStorage());
3396 uno::Reference < io::XStream > xSrcStream =
3397 xSrcRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READ );
3398 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xSrcStream );
3400 if ( pStream && SVSTREAM_OK == pStream->GetError())
3402 pStream->Seek(STREAM_SEEK_TO_END);
3403 pFib->lcbCmds = pStream->Tell();
3404 pStream->Seek(0);
3406 sal_uInt8 *pBuffer = new sal_uInt8[pFib->lcbCmds];
3407 pStream->Read(pBuffer, pFib->lcbCmds);
3408 pTableStrm->Write(pBuffer, pFib->lcbCmds);
3409 delete[] pBuffer;
3413 delete pStream;
3415 catch ( uno::Exception& )
3419 // set len to FIB
3420 pFib->lcbCmds = pTableStrm->Tell() - pFib->fcCmds;
3423 void WW8SHDLong::Write( WW8Export& rExport )
3425 rExport.InsUInt32( m_cvFore );
3426 rExport.InsUInt32( m_cvBack );
3427 rExport.InsUInt16( m_ipat );
3430 void WW8Export::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
3432 ASSERT( bWrtWW8, "No 95 export yet" );
3433 if ( !bWrtWW8 )
3434 return;
3436 const ::sw::mark::IFieldmark* pFieldmark = &rFieldmark;
3437 const ::sw::mark::ICheckboxFieldmark* pAsCheckbox = dynamic_cast< const ::sw::mark::ICheckboxFieldmark* >( pFieldmark );
3440 ASSERT(rFieldmark.GetFieldname().equalsAscii( ECMA_FORMTEXT ) || rFieldmark.GetFieldname().equalsAscii( ECMA_FORMDROPDOWN ) || rFieldmark.GetFieldname().equalsAscii( ECMA_FORMCHECKBOX ), "Unknown field type!!!");
3441 if ( ! ( rFieldmark.GetFieldname().equalsAscii( ECMA_FORMTEXT ) ||
3442 rFieldmark.GetFieldname().equalsAscii( ECMA_FORMDROPDOWN ) ||
3443 rFieldmark.GetFieldname().equalsAscii( ECMA_FORMCHECKBOX ) ) )
3444 return;
3446 int type = 0; // TextFieldmark
3447 if ( pAsCheckbox )
3448 type = 1;
3449 if ( rFieldmark.GetFieldname().equalsAscii( ECMA_FORMDROPDOWN ) )
3450 type=2;
3452 const String ffname = rFieldmark.getParam("name").second;
3454 ULONG nDataStt = pDataStrm->Tell();
3455 pChpPlc->AppendFkpEntry(Strm().Tell());
3457 WriteChar(0x01);
3458 static BYTE aArr1[] =
3460 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
3462 0x06, 0x08, 0x01, // sprmCFData
3463 0x55, 0x08, 0x01, // sprmCFSpec
3464 0x02, 0x08, 0x01 // sprmCFFldVanish
3466 BYTE* pDataAdr = aArr1 + 2;
3467 Set_UInt32(pDataAdr, nDataStt);
3469 pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aArr1 ), aArr1 );
3471 sal_uInt8 aFldHeader[] =
3473 0xFF, 0xFF, 0xFF, 0xFF, // Unicode Marker...
3474 0, 0, 0, 0, 0, 0 //, 0, 0
3477 aFldHeader[4] |= (type & 0x03);
3478 int ffres = 0; // rFieldmark.GetFFRes();
3479 if ( pAsCheckbox && pAsCheckbox->IsChecked() )
3480 ffres = 1;
3481 else if ( type == 2 )
3482 ffres = rFieldmark.getParam( ECMA_FORMDROPDOWN_RESULT, "0" ).second.toInt32();
3483 aFldHeader[4] |= ( (ffres<<2) & 0x7C );
3485 std::vector< ::rtl::OUString > aListItems;
3486 if (type==2)
3488 aFldHeader[5] |= 0x80; // ffhaslistbox
3489 for ( int i = 0; i < rFieldmark.getNumOfParams() ; i++ )
3491 if (rFieldmark.getParam(i).first.compareToAscii(ECMA_FORMDROPDOWN_LISTENTRY)==0)
3492 aListItems.push_back(rFieldmark.getParam(i).second);
3496 const ::rtl::OUString ffdeftext;
3497 const ::rtl::OUString ffformat;
3498 const ::rtl::OUString ffhelptext;
3499 const ::rtl::OUString ffstattext;
3500 const ::rtl::OUString ffentrymcr;
3501 const ::rtl::OUString ffexitmcr;
3504 const sal_uInt8 aFldData[] =
3506 0,0,0,0, // len of struct
3507 0x44,0, // the start of "next" data
3508 0,0,0,0,0,0,0,0,0,0, // PIC-Structure! /10
3509 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3510 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3511 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3512 0,0,0,0, // / /4
3514 int slen = sizeof( aFldData )
3515 + sizeof( aFldHeader )
3516 + 2*ffname.Len() + 4
3517 + 2*ffdeftext.getLength() + 4
3518 + 2*ffformat.getLength() + 4
3519 + 2*ffhelptext.getLength() + 4
3520 + 2*ffstattext.getLength() + 4
3521 + 2*ffentrymcr.getLength() + 4
3522 + 2*ffexitmcr.getLength() + 4;
3523 if ( type==2 ) {
3524 slen += 2; // for 0xFF, 0xFF
3525 slen += 4; // for num of list items
3526 const int items = aListItems.size();
3527 for( int i = 0; i < items; i++ ) {
3528 rtl::OUString item = aListItems[i];
3529 slen += 2 * item.getLength() + 2;
3532 #ifdef OSL_BIGENDIAN
3533 slen = SWAPLONG( slen );
3534 #endif // OSL_BIGENDIAN
3535 *( (sal_uInt32 *)aFldData ) = slen;
3536 int len = sizeof( aFldData );
3537 OSL_ENSURE( len == 0x44, "SwWW8Writer::WriteFormData(..) - wrong aFldData length" );
3538 pDataStrm->Write( aFldData, len );
3540 len = sizeof( aFldHeader );
3541 OSL_ENSURE( len == 8, "SwWW8Writer::WriteFormData(..) - wrong aFldHeader length" );
3543 pDataStrm->Write( aFldHeader, len );
3545 SwWW8Writer::WriteString_xstz( *pDataStrm, ffname, true ); // Form field name
3547 if ( type == 0 )
3548 SwWW8Writer::WriteString_xstz( *pDataStrm, ffdeftext, true );
3549 else
3550 pDataStrm->WriteNumber( (sal_uInt16)0 );
3552 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffformat ), true );
3553 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffhelptext ), true );
3554 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffstattext ), true );
3555 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffentrymcr ), true );
3556 SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffexitmcr ), true );
3557 if (type==2) {
3558 *pDataStrm<<(sal_uInt16)0xFFFF;
3559 const int items=aListItems.size();
3560 *pDataStrm<<(sal_uInt32)items;
3561 for(int i=0;i<items;i++) {
3562 rtl::OUString item=aListItems[i];
3563 SwWW8Writer::WriteString_xstz( *pDataStrm, item, false );
3568 void WW8Export::WriteHyperlinkData( const sw::mark::IFieldmark& rFieldmark )
3570 //@TODO implement me !!!
3573 void WW8AttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
3575 SVBT16 nStyle;
3576 ShortToSVBT16( m_rWW8Export.nStyleBeforeFly, nStyle );
3578 #ifdef DEBUG
3579 ::std::clog << "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner->toString();
3580 #endif
3582 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3584 if (pNodeInfoInner->isEndOfCell())
3586 #ifdef DEBUG
3587 ::std::clog << "<endOfCell/>" << ::std::endl;
3588 #endif
3589 m_rWW8Export.WriteCR(pNodeInfoInner);
3591 m_rWW8Export.pO->Insert( (BYTE*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
3592 TableInfoCell(pNodeInfoInner);
3593 m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
3594 m_rWW8Export.pO->GetData() );
3596 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3599 if (pNodeInfoInner->isEndOfLine())
3601 #ifdef DEBUG
3602 ::std::clog << "<endOfLine/>" << ::std::endl;
3603 #endif
3604 TableRowEnd(pNodeInfoInner->getDepth());
3606 m_rWW8Export.pO->Insert( (BYTE*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
3607 TableInfoRow(pNodeInfoInner);
3608 m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
3609 m_rWW8Export.pO->GetData() );
3611 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
3613 #ifdef DEBUG
3614 ::std::clog << "</OutWW8_TableNodeInfoInner>" << ::std::endl;
3615 #endif
3618 void MSWordExportBase::OutputEndNode( const SwEndNode &rNode )
3620 #ifdef DEBUG
3621 ::std::clog << "<OutWW8_SwEndNode>" << dbg_out(&rNode) << ::std::endl;
3622 #endif
3624 ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = mpTableInfo->getTableNodeInfo( &rNode );
3626 if (pNodeInfo)
3628 if (pNodeInfo.get() != NULL)
3630 #ifdef DEBUG
3631 ::std::clog << pNodeInfo->toString() << ::std::endl;
3632 #endif
3634 const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
3635 ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt(aInners.begin());
3636 ww8::WW8TableNodeInfo::Inners_t::const_iterator aEnd(aInners.end());
3637 while (aIt != aEnd)
3639 ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
3640 AttrOutput().TableNodeInfoInner(pInner);
3641 aIt++;
3645 #ifdef DEBUG
3646 ::std::clog << "</OutWW8_SwEndNode>" << ::std::endl;
3647 #endif
3650 /* vi:set tabstop=4 shiftwidth=4 expandtab: */