1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include <com/sun/star/embed/ElementModes.hpp>
24 #include <com/sun/star/embed/XStorage.hpp>
25 #include <unotools/ucbstreamhelper.hxx>
29 #include <hintids.hxx>
30 #include <string.h> // memcpy()
31 #include <osl/endian.h>
34 #include <unotools/fltrcfg.hxx>
35 #include <vcl/salbtype.hxx>
36 #include <sot/storage.hxx>
37 #include <svl/zformat.hxx>
38 #include <sfx2/docinf.hxx>
39 #include <editeng/tstpitem.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdpage.hxx>
42 #include <editeng/hyphenzoneitem.hxx>
43 #include <editeng/langitem.hxx>
44 #include <filter/msfilter/msoleexp.hxx>
45 #include <editeng/lrspitem.hxx>
46 #include <editeng/ulspitem.hxx>
47 #include <editeng/boxitem.hxx>
48 #include <editeng/brushitem.hxx>
49 #include <swtypes.hxx>
51 #include <swtblfmt.hxx>
52 #include <txatbase.hxx>
53 #include <fmtcntnt.hxx>
54 #include <fmtpdsc.hxx>
55 #include <fmtrowsplt.hxx>
58 #include <viewopt.hxx>
62 #include <shellio.hxx>
63 #include <docstat.hxx>
64 #include <pagedesc.hxx>
66 #include <swtable.hxx>
70 #include <swmodule.hxx>
71 #include <section.hxx>
72 #include <swfltopt.hxx>
73 #include <fmtinfmt.hxx>
74 #include <txtinet.hxx>
77 #include <svtools/imap.hxx>
78 #include <svtools/imapobj.hxx>
79 #include <tools/urlobj.hxx>
80 #include <mdiexp.hxx> // Progress
81 #include <statstr.hrc> // ResId for the status bar
82 #include <fmtline.hxx>
83 #include <fmtfsize.hxx>
84 #include <comphelper/extract.hxx>
85 #include <comphelper/stlunosequence.hxx>
86 #include <comphelper/string.hxx>
87 #include <doctok/sprmids.hxx>
89 #include "writerhelper.hxx"
90 #include "writerwordglue.hxx"
91 #include "ww8attributeoutput.hxx"
93 #include <IDocumentMarkAccess.hxx>
94 #include <xmloff/odffields.hxx>
96 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
97 #include <com/sun/star/document/XDocumentProperties.hpp>
99 #include "dbgoutsw.hxx"
101 #include <sfx2/docfile.hxx>
102 #include <sfx2/request.hxx>
103 #include <sfx2/frame.hxx>
104 #include <svl/stritem.hxx>
105 #include <unotools/tempfile.hxx>
106 #include <filter/msfilter/mscodec.hxx>
107 #include <filter/msfilter/svxmsbas.hxx>
108 #include <osl/time.h>
109 #include <rtl/random.h>
110 #include <vcl/svapp.hxx>
111 #include "WW8Sttbf.hxx"
112 #include <editeng/charrotateitem.hxx>
113 #include "WW8FibData.hxx"
114 #include "numrule.hxx"//For i120928
117 using namespace sw::util
;
118 using namespace sw::types
;
120 /** FKP - Formatted disK Page
124 sal_uInt8
* pFkp
; // Fkp total ( first and only FCs and Sprms )
125 sal_uInt8
* pOfs
; // pointer to the offset area, later copied to pFkp
127 short nStartGrp
; // ab hier grpprls
130 sal_uInt8 nIMax
; // number of entry pairs
131 sal_uInt8 nOldVarLen
;
132 bool bCombined
; // true : paste not allowed
134 sal_uInt8
SearchSameSprm( sal_uInt16 nVarLen
, const sal_uInt8
* pSprms
);
136 WW8_WrFkp(ePLCFT ePl
, WW8_FC nStartFc
, bool bWrtWW8
);
138 bool Append( WW8_FC nEndFc
, sal_uInt16 nVarLen
= 0, const sal_uInt8
* pSprms
= 0 );
140 void Write( SvStream
& rStrm
, SwWW8WrGrf
& rGrf
);
142 bool IsEqualPos(WW8_FC nEndFc
) const
143 { return !bCombined
&& nIMax
&& nEndFc
== ((sal_Int32
*)pFkp
)[nIMax
]; }
144 void MergeToNew( short& rVarLen
, sal_uInt8
*& pNewSprms
);
145 bool IsEmptySprm() const
146 { return !bCombined
&& nIMax
&& !nOldVarLen
; }
147 void SetNewEnd( WW8_FC nEnd
)
148 { ((sal_Int32
*)pFkp
)[nIMax
] = nEnd
; }
150 #ifdef __WW8_NEEDS_COPY
151 WW8_FC
GetStartFc() const;
152 WW8_FC
GetEndFc() const;
154 WW8_FC
GetStartFc() const { return ((sal_Int32
*)pFkp
)[0]; };
155 WW8_FC
GetEndFc() const { return ((sal_Int32
*)pFkp
)[nIMax
]; };
156 #endif // defined __WW8_NEEDS_COPY
158 sal_uInt8
*CopyLastSprms(sal_uInt8
&rLen
, bool bVer8
);
162 // class WW8_WrPc collects all piece entries for one piece
165 WW8_CP nStartCp
; // Starting character position of the text
166 WW8_FC nStartFc
; // Starting file position of the text
167 sal_uInt16 nStatus
; // End of paragraph inside the piece?
170 WW8_WrPc(WW8_FC nSFc
, WW8_CP nSCp
)
171 : nStartCp( nSCp
), nStartFc( nSFc
), nStatus( 0x0040 )
174 void SetStatus() { nStatus
= 0x0050; }
175 sal_uInt16
GetStatus() const { return nStatus
; }
176 WW8_CP
GetStartCp() const { return nStartCp
; }
177 WW8_FC
GetStartFc() const { return nStartFc
; }
180 class WW8_WrtBookmarks
183 //! Holds information about a single bookmark.
184 struct BookmarkInfo
{
185 sal_uLong startPos
; //!< Starting character position.
186 sal_uLong endPos
; //!< Ending character position.
187 bool isField
; //!< True if the bookmark is in a field result.
188 String name
; //!< Name of this bookmark.
189 inline BookmarkInfo(sal_uLong start
, sal_uLong end
, bool isFld
, const String
& bkName
) : startPos(start
), endPos(end
), isField(isFld
), name(bkName
) {};
190 //! Operator < is defined purely for sorting.
191 inline bool operator<(const BookmarkInfo
&other
) const { return startPos
< other
.startPos
; }
193 std::vector
<BookmarkInfo
> aBookmarks
;
194 typedef std::vector
<BookmarkInfo
>::iterator BkmIter
;
196 //! Return the position in aBookmarks where the string rNm can be found.
197 BkmIter
GetPos( const String
& rNm
);
200 WW8_WrtBookmarks(const WW8_WrtBookmarks
&);
201 WW8_WrtBookmarks
& operator=(const WW8_WrtBookmarks
&);
206 //! Add a new bookmark to the list OR add an end position to an existing bookmark.
207 void Append( WW8_CP nStartCp
, const String
& rNm
, const ::sw::mark::IMark
* pBkmk
=NULL
);
208 //! Write out bookmarks to file.
209 void Write( WW8Export
& rWrt
);
210 //! Move existing field marks from one position to another.
211 void MoveFieldMarks(sal_uLong nFrom
,sal_uLong nTo
);
215 #define ANZ_DEFAULT_STYLES 16
217 // Names of the storage streams
218 #define sMainStream OUString("WordDocument")
219 #define sCompObj OUString("\1CompObj")
221 static void WriteDop( WW8Export
& rWrt
)
223 WW8Dop
& rDop
= *rWrt
.pDop
;
225 // i#78951#, store the value of unknown compatability options
226 rDop
.SetCompatabilityOptions( rWrt
.pDoc
->Getn32DummyCompatabilityOptions1());
227 rDop
.SetCompatabilityOptions2( rWrt
.pDoc
->Getn32DummyCompatabilityOptions2());
229 rDop
.fNoLeading
= !rWrt
.pDoc
->get(IDocumentSettingAccess::ADD_EXT_LEADING
);
230 rDop
.fUsePrinterMetrics
= !rWrt
.pDoc
->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE
);
232 // write default TabStop
233 const SvxTabStopItem
& rTabStop
=
234 DefaultItemGet
<SvxTabStopItem
>(*rWrt
.pDoc
, RES_PARATR_TABSTOP
);
235 rDop
.dxaTab
= (sal_uInt16
)rTabStop
[0].GetTabPos();
238 ViewShell
*pViewShell(rWrt
.pDoc
->GetCurrentViewShell());
239 if (pViewShell
&& pViewShell
->GetViewOptions()->GetZoomType() == SVX_ZOOM_PERCENT
)
240 rDop
.wScaleSaved
= pViewShell
->GetViewOptions()->GetZoom();
242 // Werte aus der DocStatistik (werden aufjedenfall fuer die
243 // DocStat-Felder benoetigt!)
244 rDop
.fWCFtnEdn
= true; // because they are included in StarWriter
246 const SwDocStat
& rDStat
= rWrt
.pDoc
->GetDocStat();
247 rDop
.cWords
= rDStat
.nWord
;
248 rDop
.cCh
= rDStat
.nChar
;
249 rDop
.cPg
= static_cast< sal_Int16
>(rDStat
.nPage
);
250 rDop
.cParas
= rDStat
.nPara
;
251 rDop
.cLines
= rDStat
.nPara
;
253 SwDocShell
*pDocShell(rWrt
.pDoc
->GetDocShell());
254 OSL_ENSURE(pDocShell
, "no SwDocShell");
255 uno::Reference
<document::XDocumentProperties
> xDocProps
;
256 uno::Reference
<beans::XPropertySet
> xProps
;
258 uno::Reference
<lang::XComponent
> xModelComp(pDocShell
->GetModel(),
260 xProps
= uno::Reference
<beans::XPropertySet
>(xModelComp
,
262 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
263 xModelComp
, uno::UNO_QUERY_THROW
);
264 xDocProps
= xDPS
->getDocumentProperties();
265 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
267 rDop
.lKeyProtDoc
= pDocShell
->GetModifyPasswordHash();
270 if ((rWrt
.pSepx
&& rWrt
.pSepx
->DocumentIsProtected()) ||
271 rDop
.lKeyProtDoc
!= 0)
273 rDop
.fProtEnabled
= 1;
277 rDop
.fProtEnabled
= 0;
282 rDop
.dttmCreated
= rDop
.dttmRevised
= rDop
.dttmLastPrint
= 0x45FBAC69;
286 ::util::DateTime uDT
= xDocProps
->getCreationDate();
287 Date
aD(uDT
.Day
, uDT
.Month
, uDT
.Year
);
288 Time
aT(uDT
.Hours
, uDT
.Minutes
, uDT
.Seconds
, uDT
.NanoSeconds
);
289 rDop
.dttmCreated
= sw::ms::DateTime2DTTM(DateTime(aD
,aT
));
290 uDT
= xDocProps
->getModificationDate();
291 Date
aD2(uDT
.Day
, uDT
.Month
, uDT
.Year
);
292 Time
aT2(uDT
.Hours
, uDT
.Minutes
, uDT
.Seconds
, uDT
.NanoSeconds
);
293 rDop
.dttmRevised
= sw::ms::DateTime2DTTM(DateTime(aD2
,aT2
));
294 uDT
= xDocProps
->getPrintDate();
295 Date
aD3(uDT
.Day
, uDT
.Month
, uDT
.Year
);
296 Time
aT3(uDT
.Hours
, uDT
.Minutes
, uDT
.Seconds
, uDT
.NanoSeconds
);
297 rDop
.dttmLastPrint
= sw::ms::DateTime2DTTM(DateTime(aD3
,aT3
));
300 // Also, the DocStat fields in headers, footers are not calculated correctly.
301 // ( we do not have this fields! )
303 // and also for the Headers and Footers
304 rDop
.cWordsFtnEnd
= rDStat
.nWord
;
305 rDop
.cChFtnEdn
= rDStat
.nChar
;
306 rDop
.cPgFtnEdn
= (sal_Int16
)rDStat
.nPage
;
307 rDop
.cParasFtnEdn
= rDStat
.nPara
;
308 rDop
.cLinesFtnEdn
= rDStat
.nPara
;
310 rDop
.fDontUseHTMLAutoSpacing
= (rWrt
.pDoc
->get(IDocumentSettingAccess::PARA_SPACE_MAX
) != 0);
312 rDop
.fExpShRtn
= !rWrt
.pDoc
->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
); // #i56856#
314 rDop
.Write( *rWrt
.pTableStrm
, *rWrt
.pFib
);
317 const sal_Unicode
*WW8DopTypography::GetJapanNotBeginLevel1()
319 static const sal_Unicode aJapanNotBeginLevel1
[nMaxFollowing
] =
322 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
323 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
324 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
325 0x300f, 0x3011, 0x3015, 0x309b, 0x309c, 0x309d, 0x309e, 0x30fb,
326 0x30fd, 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a,
327 0xff1b, 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65,
328 0xff9e, 0xff9f, 0xffe0
330 return &aJapanNotBeginLevel1
[0];
333 const sal_Unicode
*WW8DopTypography::GetJapanNotEndLevel1()
335 static const sal_Unicode aJapanNotEndLevel1
[nMaxLeading
] =
338 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
339 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
340 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
342 return &aJapanNotEndLevel1
[0];
345 static int lcl_CmpBeginEndChars( const OUString
& rSWStr
,
346 const sal_Unicode
* pMSStr
, int nMSStrByteLen
)
348 nMSStrByteLen
/= sizeof( sal_Unicode
);
349 if( nMSStrByteLen
> rSWStr
.getLength() )
350 nMSStrByteLen
= rSWStr
.getLength()+1;
351 nMSStrByteLen
*= sizeof( sal_Unicode
);
353 return memcmp( rSWStr
.getStr(), pMSStr
, nMSStrByteLen
);
357 Converts the OOo Asian Typography into a best fit match for Microsoft
358 Asian typography. This structure is actually dumped to disk within the
359 Dop Writer. Assumption is that rTypo is cleared to 0 on entry
361 void WW8Export::ExportDopTypography(WW8DopTypography
&rTypo
)
363 static const sal_Unicode aLangNotBegin
[4][WW8DopTypography::nMaxFollowing
]=
367 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
368 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
369 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
370 0x300f, 0x3011, 0x3015, 0x3041, 0x3043, 0x3045, 0x3047, 0x3049,
371 0x3063, 0x3083, 0x3085, 0x3087, 0x308e, 0x309b, 0x309c, 0x309d,
372 0x309e, 0x30a1, 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30c3, 0x30e3,
373 0x30e5, 0x30e7, 0x30ee, 0x30f5, 0x30f6, 0x30fb, 0x30fc, 0x30fd,
374 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b,
375 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65, 0xff67,
376 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
377 0xff70, 0xff9e, 0xff9f, 0xffe0
381 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
382 0x007d, 0x00a8, 0x00b7, 0x02c7, 0x02c9, 0x2015, 0x2016, 0x2019,
383 0x201d, 0x2026, 0x2236, 0x3001, 0x3002, 0x3003, 0x3005, 0x3009,
384 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x3017, 0xff01, 0xff02,
385 0xff07, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
386 0xff40, 0xff5c, 0xff5d, 0xff5e, 0xffe0
390 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
391 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2032, 0x2033,
392 0x2103, 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0xff01,
393 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
396 //Traditional Chinese
398 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
399 0x007d, 0x00a2, 0x00b7, 0x2013, 0x2014, 0x2019, 0x201d, 0x2022,
400 0x2025, 0x2026, 0x2027, 0x2032, 0x2574, 0x3001, 0x3002, 0x3009,
401 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x301e, 0xfe30, 0xfe31,
402 0xfe33, 0xfe34, 0xfe36, 0xfe38, 0xfe3a, 0xfe3c, 0xfe3e, 0xfe40,
403 0xfe42, 0xfe44, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55,
404 0xfe56, 0xfe57, 0xfe5a, 0xfe5c, 0xfe5e, 0xff01, 0xff09, 0xff0c,
405 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff5c, 0xff5d, 0xff64
409 static const sal_Unicode aLangNotEnd
[4][WW8DopTypography::nMaxLeading
] =
413 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
414 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
415 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
419 0x0028, 0x005b, 0x007b, 0x00b7, 0x2018, 0x201c, 0x3008, 0x300a,
420 0x300c, 0x300e, 0x3010, 0x3014, 0x3016, 0xff08, 0xff0e, 0xff3b,
421 0xff5b, 0xffe1, 0xffe5
425 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c,
426 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04, 0xff08,
427 0xff3b, 0xff5b, 0xffe6
429 //Traditional Chinese
431 0x0028, 0x005b, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c, 0x2035,
432 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0x301d, 0xfe35,
433 0xfe37, 0xfe39, 0xfe3b, 0xfe3d, 0xfe3f, 0xfe41, 0xfe43, 0xfe59,
434 0xfe5b, 0xfe5d, 0xff08, 0xff5b
438 const i18n::ForbiddenCharacters
*pForbidden
= 0;
439 const i18n::ForbiddenCharacters
*pUseMe
= 0;
440 sal_uInt8 nUseReserved
=0;
443 Now we have some minor difficult issues, to wit...
444 a. MicroSoft Office can only store one set of begin and end characters in
445 a given document, not one per language.
446 b. StarOffice has only a concept of one set of begin and end characters for
447 a given language, i.e. not the two levels of kinsoku in japanese
449 What is unknown as yet is if our default begin and end chars for
450 japanese, chinese tradition, chinese simplified and korean are different
451 in Word and Writer. I already suspect that they are different between
452 different version of word itself.
454 So what have come up with is to simply see if any of the four languages
455 in OOo have been changed away from OUR defaults, and if one has then
456 export that. If more than one has in the future we may hack in something
457 which examines our document properties to see which language is used the
458 most and choose that, for now we choose the first and throw an ASSERT
461 /*Our default Japanese Level is 2, this is a special MS hack to set this*/
464 for (rTypo
.reserved1
=8;rTypo
.reserved1
>0;rTypo
.reserved1
-=2)
466 if (0 != (pForbidden
= pDoc
->getForbiddenCharacters(rTypo
.GetConvertedLang(),
469 int nIdx
= (rTypo
.reserved1
-2)/2;
470 if( lcl_CmpBeginEndChars( pForbidden
->endLine
,
471 aLangNotEnd
[ nIdx
], sizeof(aLangNotEnd
[ nIdx
]) ) ||
472 lcl_CmpBeginEndChars( pForbidden
->beginLine
,
473 aLangNotBegin
[ nIdx
], sizeof(aLangNotBegin
[ nIdx
]) ) )
475 //One exception for Japanese, if it matches a level 1 we
476 //can use one extra flag for that, rather than use a custom
477 if (rTypo
.GetConvertedLang() == LANGUAGE_JAPANESE
)
480 !lcl_CmpBeginEndChars
483 rTypo
.GetJapanNotEndLevel1(),
484 rTypo
.nMaxLeading
* sizeof(sal_Unicode
)
487 !lcl_CmpBeginEndChars
489 pForbidden
->beginLine
,
490 rTypo
.GetJapanNotBeginLevel1(),
491 rTypo
.nMaxFollowing
* sizeof(sal_Unicode
)
503 nUseReserved
= rTypo
.reserved1
;
504 rTypo
.iLevelOfKinsoku
= 2;
511 OSL_ENSURE( nNoNeeded
<=1, "Example of unexportable forbidden chars" );
512 rTypo
.reserved1
=nUseReserved
;
513 if (rTypo
.iLevelOfKinsoku
)
515 rTypo
.cchFollowingPunct
= msword_cast
<sal_Int16
>
516 (pUseMe
->beginLine
.getLength());
517 if (rTypo
.cchFollowingPunct
> WW8DopTypography::nMaxFollowing
- 1)
518 rTypo
.cchFollowingPunct
= WW8DopTypography::nMaxFollowing
- 1;
520 rTypo
.cchLeadingPunct
= msword_cast
<sal_Int16
>
521 (pUseMe
->endLine
.getLength());
522 if (rTypo
.cchLeadingPunct
> WW8DopTypography::nMaxLeading
- 1)
523 rTypo
.cchLeadingPunct
= WW8DopTypography::nMaxLeading
-1;
525 memcpy(rTypo
.rgxchFPunct
,pUseMe
->beginLine
.getStr(),
526 (rTypo
.cchFollowingPunct
+1)*2);
528 memcpy(rTypo
.rgxchLPunct
,pUseMe
->endLine
.getStr(),
529 (rTypo
.cchLeadingPunct
+1)*2);
532 const IDocumentSettingAccess
* pIDocumentSettingAccess
= GetWriter().getIDocumentSettingAccess();
534 rTypo
.fKerningPunct
= pIDocumentSettingAccess
->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION
);
535 rTypo
.iJustification
= pDoc
->getCharacterCompressionType();
538 // It can only be found something with this method, if it is used within
539 // WW8_SwAttrIter::OutAttr() and WW8Export::OutputItemSet()
540 const SfxPoolItem
* MSWordExportBase::HasItem( sal_uInt16 nWhich
) const
542 const SfxPoolItem
* pItem
=0;
545 // if write a EditEngine text, then the WhichIds are greater as
546 // ourer own Ids. So the Id have to translate from our into the
548 nWhich
= sw::hack::GetSetWhichFromSwDocWhich(*pISet
, *pDoc
, nWhich
);
549 if (nWhich
&& SFX_ITEM_SET
!= pISet
->GetItemState(nWhich
, true, &pItem
))
553 pItem
= pChpIter
->HasTextItem( nWhich
);
556 OSL_ENSURE( !this, "Where is my ItemSet / pChpIter ?" );
562 const SfxPoolItem
& MSWordExportBase::GetItem(sal_uInt16 nWhich
) const
564 const SfxPoolItem
* pItem
;
567 // if write a EditEngine text, then the WhichIds are greater as
568 // ourer own Ids. So the Id have to translate from our into the
570 nWhich
= sw::hack::GetSetWhichFromSwDocWhich(*pISet
, *pDoc
, nWhich
);
571 OSL_ENSURE(nWhich
!= 0, "All broken, Impossible");
572 pItem
= &pISet
->Get(nWhich
, true);
575 pItem
= &pChpIter
->GetItem( nWhich
);
578 OSL_ENSURE( !this, "Where is my ItemSet / pChpIter ?" );
584 //------------------------------------------------------------------------------
586 WW8_WrPlc1::WW8_WrPlc1( sal_uInt16 nStructSz
)
587 : nStructSiz( nStructSz
)
589 nDataLen
= 16 * nStructSz
;
590 pData
= new sal_uInt8
[ nDataLen
];
593 WW8_WrPlc1::~WW8_WrPlc1()
598 WW8_CP
WW8_WrPlc1::Prev() const
600 bool b
= !aPos
.empty();
601 OSL_ENSURE(b
,"Prev called on empty list");
602 return b
? aPos
.back() : 0;
605 void WW8_WrPlc1::Append( WW8_CP nCp
, const void* pNewData
)
607 sal_uLong nInsPos
= aPos
.size() * nStructSiz
;
608 aPos
.push_back( nCp
);
609 if( nDataLen
< nInsPos
+ nStructSiz
)
611 sal_uInt8
* pNew
= new sal_uInt8
[ 2 * nDataLen
];
612 memcpy( pNew
, pData
, nDataLen
);
617 memcpy( pData
+ nInsPos
, pNewData
, nStructSiz
);
620 void WW8_WrPlc1::Finish( sal_uLong nLastCp
, sal_uLong nSttCp
)
624 aPos
.push_back( nLastCp
);
626 for( sal_uInt32 n
= 0; n
< aPos
.size(); ++n
)
632 void WW8_WrPlc1::Write( SvStream
& rStrm
)
635 for( i
= 0; i
< aPos
.size(); ++i
)
636 SwWW8Writer::WriteLong( rStrm
, aPos
[i
] );
638 rStrm
.Write( pData
, (i
-1) * nStructSiz
);
642 // Class WW8_WrPlcFld for fields
644 bool WW8_WrPlcFld::Write( WW8Export
& rWrt
)
646 if( WW8_WrPlc1::Count() <= 1 )
654 pfc
= &rWrt
.pFib
->fcPlcffldMom
;
655 plc
= &rWrt
.pFib
->lcbPlcffldMom
;
658 pfc
= &rWrt
.pFib
->fcPlcffldHdr
;
659 plc
= &rWrt
.pFib
->lcbPlcffldHdr
;
663 pfc
= &rWrt
.pFib
->fcPlcffldFtn
;
664 plc
= &rWrt
.pFib
->lcbPlcffldFtn
;
668 pfc
= &rWrt
.pFib
->fcPlcffldEdn
;
669 plc
= &rWrt
.pFib
->lcbPlcffldEdn
;
673 pfc
= &rWrt
.pFib
->fcPlcffldAtn
;
674 plc
= &rWrt
.pFib
->lcbPlcffldAtn
;
678 pfc
= &rWrt
.pFib
->fcPlcffldTxbx
;
679 plc
= &rWrt
.pFib
->lcbPlcffldTxbx
;
683 pfc
= &rWrt
.pFib
->fcPlcffldHdrTxbx
;
684 plc
= &rWrt
.pFib
->lcbPlcffldHdrTxbx
;
694 sal_uLong nFcStart
= rWrt
.pTableStrm
->Tell();
695 WW8_WrPlc1::Write( *rWrt
.pTableStrm
);
697 *plc
= rWrt
.pTableStrm
->Tell() - nFcStart
;
702 bool WW8_WrMagicTable::Write( WW8Export
& rWrt
)
704 if( WW8_WrPlc1::Count() <= 1 )
706 sal_uLong nFcStart
= rWrt
.pTableStrm
->Tell();
707 WW8_WrPlc1::Write( *rWrt
.pTableStrm
);
708 rWrt
.pFib
->fcPlcfTch
= nFcStart
;
709 rWrt
.pFib
->lcbPlcfTch
= rWrt
.pTableStrm
->Tell() - nFcStart
;
713 void WW8_WrMagicTable::Append( WW8_CP nCp
, sal_uLong nData
)
717 Tell the undocumented table hack that everything between here and the last
718 table position is nontable text, don't do it if the previous position is
719 the same as this one, as that would be a region of 0 length
721 if ((!Count()) || (Prev() != nCp
))
723 UInt32ToSVBT32(nData
,nLittle
);
724 WW8_WrPlc1::Append(nCp
, nLittle
);
728 //--------------------------------------------------------------------------
730 void SwWW8Writer::FillCount( SvStream
& rStrm
, sal_uLong nCount
)
732 static const sal_uInt32 aNulls
[16] =
734 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 64 Byte
739 rStrm
.Write( aNulls
, 64 ); // in steps of 64-Byte
742 rStrm
.Write( aNulls
, nCount
); // write the rest ( 0 .. 64 Bytes )
745 sal_uLong
SwWW8Writer::FillUntil( SvStream
& rStrm
, sal_uLong nEndPos
)
747 sal_uLong nCurPos
= rStrm
.Tell();
748 if( !nEndPos
) // nEndPos == 0 -> next Page
749 nEndPos
= (nCurPos
+ 0x1ff) & ~0x1ffUL
;
751 if( nEndPos
> nCurPos
)
752 SwWW8Writer::FillCount( rStrm
, nEndPos
- nCurPos
);
753 #if OSL_DEBUG_LEVEL > 0
755 OSL_ENSURE( nEndPos
== nCurPos
, "Falsches FillUntil()" );
761 //--------------------------------------------------------------------------
763 WW8_WrPlcPn::WW8_WrPlcPn( WW8Export
& rWr
, ePLCFT ePl
, WW8_FC nStartFc
)
764 : rWrt(rWr
), nFkpStartPage(0), ePlc(ePl
), nMark(0)
766 WW8_WrFkp
* pF
= new WW8_WrFkp( ePlc
, nStartFc
, rWrt
.bWrtWW8
);
767 aFkps
.push_back( pF
);
770 WW8_WrPlcPn::~WW8_WrPlcPn()
774 sal_uInt8
*WW8_WrPlcPn::CopyLastSprms(sal_uInt8
&rLen
)
776 WW8_WrFkp
& rF
= aFkps
.back();
777 return rF
.CopyLastSprms(rLen
, rWrt
.bWrtWW8
);
780 void WW8_WrPlcPn::AppendFkpEntry(WW8_FC nEndFc
,short nVarLen
,const sal_uInt8
* pSprms
)
782 WW8_WrFkp
* pF
= &aFkps
.back();
784 // big sprm? build the sprmPHugePapx
785 sal_uInt8
* pNewSprms
= (sal_uInt8
*)pSprms
;
786 sal_uInt8 aHugePapx
[ 8 ];
787 if( rWrt
.bWrtWW8
&& PAP
== ePlc
&& 488 < nVarLen
)
789 sal_uInt8
* p
= aHugePapx
;
790 *p
++ = *pSprms
++; // set style Id
794 long nDataPos
= rWrt
.pDataStrm
->Tell();
795 SwWW8Writer::WriteShort( *rWrt
.pDataStrm
, nVarLen
);
796 rWrt
.pDataStrm
->Write( pSprms
, nVarLen
);
798 Set_UInt16( p
, 0x6646 ); // set SprmCode
799 Set_UInt32( p
, nDataPos
); // set startpos (FC) in the datastream
800 nVarLen
= static_cast< short >(p
- aHugePapx
);
801 pSprms
= pNewSprms
= aHugePapx
;
803 // if append at the same FC-EndPos and there are sprms, then get the old
804 // sprms and erase it; they will append now with the new sprms
805 else if( nVarLen
&& pF
->IsEqualPos( nEndFc
))
806 pF
->MergeToNew( nVarLen
, pNewSprms
);
807 // has the prev EndFC an empty sprm and the current is empty too, then
808 // expand only the old EndFc to the new EndFc
809 else if( !nVarLen
&& pF
->IsEmptySprm() )
811 pF
->SetNewEnd( nEndFc
);
815 bool bOk
= pF
->Append(nEndFc
, nVarLen
, pNewSprms
);
819 pF
= new WW8_WrFkp( ePlc
, pF
->GetEndFc(), rWrt
.bWrtWW8
); // Start new Fkp == end of old Fkp
821 aFkps
.push_back( pF
);
822 if( !pF
->Append( nEndFc
, nVarLen
, pNewSprms
) )
824 OSL_ENSURE( !this, "Sprm liess sich nicht einfuegen" );
827 if( pNewSprms
!= pSprms
) //Merge to new has created a new block
831 void WW8_WrPlcPn::WriteFkps()
833 nFkpStartPage
= (sal_uInt16
) ( SwWW8Writer::FillUntil( rWrt
.Strm() ) >> 9 );
835 for( sal_uInt16 i
= 0; i
< aFkps
.size(); i
++ )
836 aFkps
[ i
].Write( rWrt
.Strm(), *rWrt
.pGrf
);
840 rWrt
.pFib
->pnChpFirst
= nFkpStartPage
;
841 rWrt
.pFib
->cpnBteChp
= aFkps
.size();
845 rWrt
.pFib
->pnPapFirst
= nFkpStartPage
;
846 rWrt
.pFib
->cpnBtePap
= aFkps
.size();
850 void WW8_WrPlcPn::WritePlc()
852 sal_uLong nFcStart
= rWrt
.pTableStrm
->Tell();
855 for( i
= 0; i
< aFkps
.size(); i
++ )
856 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
,
857 aFkps
[ i
].GetStartFc() );
859 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
,
860 aFkps
[ i
- 1 ].GetEndFc() );
862 // fuer jedes FKP die Page ausgeben
863 if( rWrt
.bWrtWW8
) // for WW97 Long output
864 for ( i
= 0; i
< aFkps
.size(); i
++)
865 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, i
+ nFkpStartPage
);
866 else // for WW95 Short output
867 for ( i
= 0; i
< aFkps
.size(); i
++)
868 SwWW8Writer::WriteShort( *rWrt
.pTableStrm
, i
+ nFkpStartPage
);
872 rWrt
.pFib
->fcPlcfbteChpx
= nFcStart
;
873 rWrt
.pFib
->lcbPlcfbteChpx
= rWrt
.pTableStrm
->Tell() - nFcStart
;
877 rWrt
.pFib
->fcPlcfbtePapx
= nFcStart
;
878 rWrt
.pFib
->lcbPlcfbtePapx
= rWrt
.pTableStrm
->Tell() - nFcStart
;
882 //--------------------------------------------------------------------------
884 WW8_WrFkp::WW8_WrFkp(ePLCFT ePl
, WW8_FC nStartFc
, bool bWrtWW8
)
885 : ePlc(ePl
), nStartGrp(511), nOldStartGrp(511),
886 nItemSize( ( CHP
== ePl
) ? 1 : ( bWrtWW8
? 13 : 7 )),
887 nIMax(0), nOldVarLen(0), bCombined(false)
889 pFkp
= (sal_uInt8
*)new sal_Int32
[128]; // 512 Byte
890 pOfs
= (sal_uInt8
*)new sal_Int32
[128]; // 512 Byte
891 memset( pFkp
, 0, 4 * 128 );
892 memset( pOfs
, 0, 4 * 128 );
893 ( (sal_Int32
*)pFkp
)[0] = nStartFc
; // 0th entry FC at nStartFc
896 WW8_WrFkp::~WW8_WrFkp()
898 delete[] (sal_Int32
*)pFkp
;
899 delete[] (sal_Int32
*)pOfs
;
902 sal_uInt8
WW8_WrFkp::SearchSameSprm( sal_uInt16 nVarLen
, const sal_uInt8
* pSprms
)
906 // if the sprms contained picture-references then never equal!
907 for( sal_uInt8 n
= static_cast< sal_uInt8
>(nVarLen
- 1); 3 < n
; --n
)
908 if( pSprms
[ n
] == GRF_MAGIC_3
&&
909 pSprms
[ n
-1 ] == GRF_MAGIC_2
&&
910 pSprms
[ n
-2 ] == GRF_MAGIC_1
)
915 for( i
= 0; i
< nIMax
; i
++ )
917 sal_uInt8 nStart
= pOfs
[i
* nItemSize
];
920 const sal_uInt8
* p
= pFkp
+ ( (sal_uInt16
)nStart
<< 1 );
923 : (((sal_uInt16
)*p
++ << 1 ) == (( nVarLen
+1) & 0xfffe)) )
924 && !memcmp( p
, pSprms
, nVarLen
) )
925 return nStart
; // found it
928 return 0; // didn't found it
931 sal_uInt8
*WW8_WrFkp::CopyLastSprms(sal_uInt8
&rLen
, bool bVer8
)
934 sal_uInt8
*pStart
=0,*pRet
=0;
939 pStart
= pFkp
+ ( nIMax
+ 1 ) * 4;
941 sal_uInt8 nStart
= *(pStart
+ (nIMax
-1) * nItemSize
);
943 const sal_uInt8
* p
= pFkp
+ ( (sal_uInt16
)nStart
<< 1 );
953 pRet
= new sal_uInt8
[rLen
];
959 bool WW8_WrFkp::Append( WW8_FC nEndFc
, sal_uInt16 nVarLen
, const sal_uInt8
* pSprms
)
961 OSL_ENSURE( !nVarLen
|| pSprms
, "Item pointer missing" );
962 OSL_ENSURE( nVarLen
< ( ( ePlc
== PAP
) ? 497U : 502U ), "Sprms too long !" );
966 OSL_ENSURE( !this, "Fkp::Append: Fkp is already combined" );
969 sal_Int32 n
= ((sal_Int32
*)pFkp
)[nIMax
]; // last entry
972 OSL_ENSURE( nEndFc
>= n
, "+Fkp: FC backwards" );
973 OSL_ENSURE( !nVarLen
|| !pSprms
|| nEndFc
!= n
,
974 "+Fkp: selber FC mehrfach benutzt" );
975 // selber FC ohne Sprm wird ohne zu mosern ignoriert.
977 return true; // ignore (do not create a new Fkp)
980 sal_uInt8 nOldP
= ( nVarLen
) ? SearchSameSprm( nVarLen
, pSprms
) : 0;
981 // Combine equal entries
982 short nOffset
=0, nPos
= nStartGrp
;
983 if (nVarLen
&& !nOldP
)
986 ? ( 13 == nItemSize
// HACK: PAP and bWrtWW8 !!
987 ? (nStartGrp
& 0xFFFE ) - nVarLen
- 1
988 : (nStartGrp
- (((nVarLen
+ 1) & 0xFFFE)+1)) & 0xFFFE )
989 : ((nStartGrp
- nVarLen
- 1) & 0xFFFE);
991 return false; // doesn't fit at all
992 nOffset
= nPos
; // save offset (can also be uneven!)
993 nPos
&= 0xFFFE; // Pos for Sprms ( gerade Pos )
996 if( (sal_uInt16
)nPos
<= ( nIMax
+ 2U ) * 4U + ( nIMax
+ 1U ) * nItemSize
)
997 // does it fits behind the CPs and offsets?
1000 ((sal_Int32
*)pFkp
)[nIMax
+ 1] = nEndFc
; // insert FC
1002 nOldVarLen
= (sal_uInt8
)nVarLen
;
1003 if( nVarLen
&& !nOldP
)
1004 { // insert it for real
1005 nOldStartGrp
= nStartGrp
;
1008 pOfs
[nIMax
* nItemSize
] = (sal_uInt8
)( nStartGrp
>> 1 );
1009 // ( DatenAnfg >> 1 ) insert
1010 sal_uInt8 nCnt
= static_cast< sal_uInt8
>(CHP
== ePlc
1011 ? ( nVarLen
< 256 ) ? (sal_uInt8
) nVarLen
: 255
1012 : ( ( nVarLen
+ 1 ) >> 1 ));
1014 pFkp
[ nOffset
] = nCnt
; // Enter data length
1015 memcpy( pFkp
+ nOffset
+ 1, pSprms
, nVarLen
); // store Sprms
1019 // do not enter for real ( no Sprms or recurrence )
1020 // DatenAnfg 0 ( no data ) or recurrence
1021 pOfs
[nIMax
* nItemSize
] = nOldP
;
1027 bool WW8_WrFkp::Combine()
1032 memcpy( pFkp
+ ( nIMax
+ 1 ) * 4, pOfs
, nIMax
* nItemSize
);
1035 ((sal_uInt8
*)pFkp
)[511] = nIMax
;
1038 #if defined OSL_BIGENDIAN // only the FCs will be rotated here
1039 sal_uInt16 i
; // the Sprms must be rotated elsewhere
1042 for( i
= 0, p
= (sal_uInt32
*)pFkp
; i
<= nIMax
; i
++, p
++ )
1043 *p
= OSL_SWAPDWORD( *p
);
1044 #endif // ifdef OSL_BIGENDIAN
1049 void WW8_WrFkp::Write( SvStream
& rStrm
, SwWW8WrGrf
& rGrf
)
1051 Combine(); // If not already combined
1053 sal_uInt8
* p
; // Suche Magic fuer nPicLocFc
1054 sal_uInt8
* pEnd
= pFkp
+ nStartGrp
;
1055 for( p
= pFkp
+ 511 - 4; p
>= pEnd
; p
-- )
1057 if( *p
!= GRF_MAGIC_1
) // search for signature 0x12 0x34 0x56 0xXX
1059 if( *(p
+1) != GRF_MAGIC_2
)
1061 if( *(p
+2) != GRF_MAGIC_3
)
1064 SVBT32 nPos
; // signature found
1065 UInt32ToSVBT32( rGrf
.GetFPos(), nPos
); // FilePos the graphics
1066 memcpy( p
, nPos
, 4 ); // patch FilePos over the signature
1068 rStrm
.Write( pFkp
, 512 );
1071 void WW8_WrFkp::MergeToNew( short& rVarLen
, sal_uInt8
*& rpNewSprms
)
1073 sal_uInt8 nStart
= pOfs
[ (nIMax
-1) * nItemSize
];
1076 sal_uInt8
* p
= pFkp
+ ( (sal_uInt16
)nStart
<< 1 );
1078 // old and new equal? Then copy only one into the new sprms
1079 if( nOldVarLen
== rVarLen
&& !memcmp( p
+1, rpNewSprms
, nOldVarLen
))
1081 sal_uInt8
* pNew
= new sal_uInt8
[ nOldVarLen
];
1082 memcpy( pNew
, p
+1, nOldVarLen
);
1087 sal_uInt8
* pNew
= new sal_uInt8
[ nOldVarLen
+ rVarLen
];
1088 memcpy( pNew
, p
+1, nOldVarLen
);
1089 memcpy( pNew
+ nOldVarLen
, rpNewSprms
, rVarLen
);
1092 rVarLen
= rVarLen
+ nOldVarLen
;
1095 // if this sprms dont used from others, remove it
1097 for (sal_uInt16 n
= 0; n
< nIMax
; ++n
)
1099 if (nStart
== pOfs
[n
* nItemSize
])
1107 nStartGrp
= nOldStartGrp
;
1108 memset( p
, 0, nOldVarLen
+1 );
1113 #ifdef __WW8_NEEDS_COPY
1115 WW8_FC
WW8_WrFkp::GetStartFc() const
1117 // wenn bCombined, dann ist das Array ab pFkp schon Bytemaessig auf LittleEndian
1118 // umgedreht, d.h. zum Herausholen der Anfangs- und Endpositionen muss
1119 // zurueckgedreht werden.
1121 return SVBT32ToUInt32( pFkp
); // 0. Element
1122 return ((sal_Int32
*)pFkp
)[0];
1125 WW8_FC
WW8_WrFkp::GetEndFc() const
1128 return SVBT32ToUInt32( &(pFkp
[nIMax
*4]) ); // nIMax-tes SVBT32-Element
1129 return ((sal_Int32
*)pFkp
)[nIMax
];
1132 #endif // defined __WW8_NEEDS_COPY
1135 // Method for managing the piece table
1136 WW8_WrPct::WW8_WrPct(WW8_FC nfcMin
, bool bSaveUniCode
)
1137 : nOldFc(nfcMin
), bIsUni(bSaveUniCode
)
1139 AppendPc( nOldFc
, bIsUni
);
1142 WW8_WrPct::~WW8_WrPct()
1146 // Fill the piece and create a new one
1147 void WW8_WrPct::AppendPc(WW8_FC nStartFc
, bool bIsUnicode
)
1149 WW8_CP nStartCp
= nStartFc
- nOldFc
; // substract the beginning of the text
1152 if ( !aPcts
.empty() )
1154 OSL_ENSURE( 1 == aPcts
.size(), "Leeres Piece !!");
1159 nOldFc
= nStartFc
; // remember StartFc as old
1162 nStartCp
>>= 1; // for Unicode: number of characters / 2
1167 nStartFc
<<= 1; // Adress * 2
1168 nStartFc
|= 0x40000000; // second last bit for non-Unicode
1171 if( !aPcts
.empty() )
1172 nStartCp
+= aPcts
.back().GetStartCp();
1174 WW8_WrPc
* pPc
= new WW8_WrPc( nStartFc
, nStartCp
);
1175 aPcts
.push_back( pPc
);
1177 bIsUni
= bIsUnicode
;
1181 void WW8_WrPct::WritePc( WW8Export
& rWrt
)
1183 sal_uLong nPctStart
;
1184 sal_uLong nOldPos
, nEndPos
;
1185 boost::ptr_vector
<WW8_WrPc
>::iterator aIter
;
1187 nPctStart
= rWrt
.pTableStrm
->Tell(); // Start piece table
1188 *rWrt
.pTableStrm
<< ( char )0x02; // Status byte PCT
1189 nOldPos
= nPctStart
+ 1; // remember Position
1190 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, 0 ); // then the length
1192 for( aIter
= aPcts
.begin(); aIter
!= aPcts
.end(); ++aIter
) // ranges
1193 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
,
1194 aIter
->GetStartCp() );
1197 // calculate the last Pos
1198 sal_uLong nStartCp
= rWrt
.pFib
->fcMac
- nOldFc
;
1200 nStartCp
>>= 1; // For Unicode: number of characters / 2
1201 nStartCp
+= aPcts
.back().GetStartCp();
1202 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, nStartCp
);
1205 for ( aIter
= aPcts
.begin(); aIter
!= aPcts
.end(); ++aIter
)
1207 SwWW8Writer::WriteShort( *rWrt
.pTableStrm
, aIter
->GetStatus());
1208 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, aIter
->GetStartFc());
1209 SwWW8Writer::WriteShort( *rWrt
.pTableStrm
, 0); // PRM=0
1212 // entries in the FIB
1213 rWrt
.pFib
->fcClx
= nPctStart
;
1214 nEndPos
= rWrt
.pTableStrm
->Tell();
1215 rWrt
.pFib
->lcbClx
= nEndPos
- nPctStart
;
1217 // and register the length as well
1218 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, nOldPos
,
1219 nEndPos
- nPctStart
-5 );
1223 void WW8_WrPct::SetParaBreak()
1225 OSL_ENSURE( !aPcts
.empty(),"SetParaBreak : aPcts.empty()" );
1226 aPcts
.back().SetStatus();
1229 WW8_CP
WW8_WrPct::Fc2Cp( sal_uLong nFc
) const
1231 OSL_ENSURE( nFc
>= (sal_uLong
)nOldFc
, "FilePos lies in front of last piece" );
1232 OSL_ENSURE( ! aPcts
.empty(), "Fc2Cp no piece available" );
1237 return nFc
+ aPcts
.back().GetStartCp();
1240 //--------------------------------------------------------------------------
1242 WW8_WrtBookmarks::WW8_WrtBookmarks()
1246 WW8_WrtBookmarks::~WW8_WrtBookmarks()
1250 void WW8_WrtBookmarks::Append( WW8_CP nStartCp
, const String
& rNm
, const ::sw::mark::IMark
* )
1252 BkmIter bkIter
= GetPos( rNm
);
1253 if( bkIter
== aBookmarks
.end() )
1255 // new bookmark -> insert with start==end
1256 aBookmarks
.push_back( BookmarkInfo(nStartCp
, nStartCp
, false, rNm
) );
1260 // old bookmark -> this should be the end position
1261 OSL_ENSURE( bkIter
->endPos
== bkIter
->startPos
, "end position is valid" );
1263 //If this bookmark was around a field in writer, then we want to move
1264 //it to the field result in word. The end is therefore one cp
1265 //backwards from the 0x15 end mark that was inserted.
1266 if (bkIter
->isField
)
1268 bkIter
->endPos
= nStartCp
;
1273 void WW8_WrtBookmarks::Write( WW8Export
& rWrt
)
1275 if (!aBookmarks
.empty())
1277 //Make sure the bookmarks are sorted in order of start position.
1278 std::sort(aBookmarks
.begin(), aBookmarks
.end());
1280 // First write the Bookmark Name Stringtable
1281 std::vector
<OUString
> aNames
;
1282 aNames
.reserve(aBookmarks
.size());
1283 for (BkmIter bIt
= aBookmarks
.begin(); bIt
< aBookmarks
.end(); ++bIt
)
1284 aNames
.push_back(bIt
->name
);
1285 rWrt
.WriteAsStringTable(aNames
, rWrt
.pFib
->fcSttbfbkmk
, rWrt
.pFib
->lcbSttbfbkmk
);
1287 // Second write the Bookmark start positions as pcf of longs
1288 SvStream
& rStrm
= rWrt
.bWrtWW8
? *rWrt
.pTableStrm
: rWrt
.Strm();
1289 rWrt
.pFib
->fcPlcfbkf
= rStrm
.Tell();
1290 for (BkmIter bIt
= aBookmarks
.begin(); bIt
< aBookmarks
.end(); ++bIt
)
1291 SwWW8Writer::WriteLong( rStrm
, bIt
->startPos
);
1292 SwWW8Writer::WriteLong(rStrm
, rWrt
.pFib
->ccpText
+ rWrt
.pFib
->ccpTxbx
);
1294 //Lastly, need to write out the end positions (sorted by end position). But
1295 //before that we need a lookup table (sorted by start position) to link
1296 //start and end positions.
1297 // Start by sorting the end positions.
1298 std::vector
<sal_uLong
> aEndSortTab
;
1299 aEndSortTab
.reserve(aBookmarks
.size());
1300 for (BkmIter bIt
= aBookmarks
.begin(); bIt
< aBookmarks
.end(); ++bIt
)
1301 aEndSortTab
.push_back(bIt
->endPos
);
1302 std::sort(aEndSortTab
.begin(), aEndSortTab
.end());
1304 //Now write out the lookups.
1305 //Note that in most cases, the positions in both vectors will be very close.
1306 for( sal_uLong i
= 0; i
< aBookmarks
.size(); ++i
)
1308 sal_uLong nEndCP
= aBookmarks
[ i
].endPos
;
1309 sal_uInt16 nPos
= i
;
1310 if( aEndSortTab
[ nPos
] > nEndCP
)
1312 while( aEndSortTab
[ --nPos
] != nEndCP
)
1315 else if( aEndSortTab
[ nPos
] < nEndCP
)
1316 while( aEndSortTab
[ ++nPos
] != nEndCP
)
1318 SwWW8Writer::WriteLong( rStrm
, nPos
);
1320 rWrt
.pFib
->lcbPlcfbkf
= rStrm
.Tell() - rWrt
.pFib
->fcPlcfbkf
;
1322 // Finally, the actual Bookmark end positions.
1323 rWrt
.pFib
->fcPlcfbkl
= rStrm
.Tell();
1324 for(sal_uLong i
= 0; i
< aEndSortTab
.size(); ++i
)
1325 SwWW8Writer::WriteLong( rStrm
, aEndSortTab
[ i
] );
1326 SwWW8Writer::WriteLong(rStrm
, rWrt
.pFib
->ccpText
+ rWrt
.pFib
->ccpTxbx
);
1327 rWrt
.pFib
->lcbPlcfbkl
= rStrm
.Tell() - rWrt
.pFib
->fcPlcfbkl
;
1331 WW8_WrtBookmarks::BkmIter
WW8_WrtBookmarks::GetPos( const String
& rNm
)
1333 for (BkmIter bIt
= aBookmarks
.begin(); bIt
< aBookmarks
.end(); ++bIt
) {
1334 if (rNm
== bIt
->name
)
1337 return aBookmarks
.end();
1340 void WW8_WrtBookmarks::MoveFieldMarks(sal_uLong nFrom
, sal_uLong nTo
)
1342 for (BkmIter i
= aBookmarks
.begin(); i
< aBookmarks
.end(); ++i
)
1344 if (i
->startPos
== nFrom
)
1347 if (i
->endPos
== nFrom
)
1356 void WW8Export::AppendBookmarks( const SwTxtNode
& rNd
,
1357 xub_StrLen nAktPos
, xub_StrLen nLen
)
1359 std::vector
< const ::sw::mark::IMark
* > aArr
;
1361 xub_StrLen nAktEnd
= nAktPos
+ nLen
;
1362 if( GetWriter().GetBookmarks( rNd
, nAktPos
, nAktEnd
, aArr
))
1364 sal_uLong nNd
= rNd
.GetIndex(), nSttCP
= Fc2Cp( Strm().Tell() );
1365 for( sal_uInt16 n
= 0; n
< aArr
.size(); ++n
)
1367 const ::sw::mark::IMark
& rBkmk
= *(aArr
[ n
]);
1368 if(dynamic_cast< const ::sw::mark::IFieldmark
*>(&rBkmk
))
1371 const SwPosition
* pPos
= &rBkmk
.GetMarkPos();
1372 const SwPosition
* pOPos
= 0;
1373 if(rBkmk
.IsExpanded())
1374 pOPos
= &rBkmk
.GetOtherMarkPos();
1375 if( pOPos
&& pOPos
->nNode
== pPos
->nNode
&&
1376 pOPos
->nContent
< pPos
->nContent
)
1379 pOPos
= &rBkmk
.GetMarkPos();
1382 if( !pOPos
|| ( nNd
== pPos
->nNode
.GetIndex() &&
1383 ( nCntnt
= pPos
->nContent
.GetIndex() ) >= nAktPos
&&
1384 nCntnt
< nAktEnd
) )
1386 sal_uLong nCp
= nSttCP
+ pPos
->nContent
.GetIndex() - nAktPos
;
1387 pBkmks
->Append(nCp
, BookmarkToWord(rBkmk
.GetName()), &rBkmk
);
1389 if( pOPos
&& nNd
== pOPos
->nNode
.GetIndex() &&
1390 ( nCntnt
= pOPos
->nContent
.GetIndex() ) >= nAktPos
&&
1393 sal_uLong nCp
= nSttCP
+ pOPos
->nContent
.GetIndex() - nAktPos
;
1394 pBkmks
->Append(nCp
, BookmarkToWord(rBkmk
.GetName()), &rBkmk
);
1400 void WW8Export::MoveFieldMarks(sal_uLong nFrom
, sal_uLong nTo
)
1402 pBkmks
->MoveFieldMarks(nFrom
, nTo
);
1405 void WW8Export::AppendBookmark( const OUString
& rName
, bool bSkip
)
1407 sal_uLong nSttCP
= Fc2Cp( Strm().Tell() ) + ( bSkip
? 1: 0 );
1408 pBkmks
->Append( nSttCP
, rName
);
1411 // #i120928 collect all the graphics of bullets applied to paragraphs
1412 int MSWordExportBase::CollectGrfsOfBullets()
1414 m_vecBulletPic
.clear();
1418 int nCountRule
= pDoc
->GetNumRuleTbl().size();
1419 for (int n
= 0; n
< nCountRule
; ++n
)
1421 const SwNumRule
&rRule
= *( pDoc
->GetNumRuleTbl().at(n
) );
1422 sal_uInt16 nLevels
= rRule
.IsContinusNum() ? 1 : 9;
1423 for (sal_uInt16 nLvl
= 0; nLvl
< nLevels
; ++nLvl
)
1425 const SwNumFmt
&rFmt
= rRule
.Get(nLvl
);
1426 if (SVX_NUM_BITMAP
!= rFmt
.GetNumberingType())
1430 const Graphic
*pGraf
= rFmt
.GetBrush()? rFmt
.GetBrush()->GetGraphic():0;
1434 for (unsigned i
= 0; i
< m_vecBulletPic
.size(); ++i
)
1436 if (m_vecBulletPic
[i
]->GetChecksum() == pGraf
->GetChecksum())
1444 m_vecBulletPic
.push_back(pGraf
);
1451 return m_vecBulletPic
.size();
1454 void MSWordExportBase::BulletDefinitions()
1456 for (size_t i
= 0; i
< m_vecBulletPic
.size(); ++i
)
1458 const MapMode
aMapMode(MAP_TWIP
);
1459 const Graphic
& rGraphic
= *m_vecBulletPic
[i
];
1460 Size
aSize(rGraphic
.GetPrefSize());
1461 if (MAP_PIXEL
== rGraphic
.GetPrefMapMode().GetMapUnit())
1462 aSize
= Application::GetDefaultDevice()->PixelToLogic(aSize
, aMapMode
);
1464 aSize
= OutputDevice::LogicToLogic(aSize
,rGraphic
.GetPrefMapMode(), aMapMode
);
1465 AttrOutput().BulletDefinition(i
, rGraphic
, aSize
);
1469 //Export Graphic of Bullets
1470 void WW8Export::ExportGrfBullet(const SwTxtNode
& rNd
)
1472 int nCount
= CollectGrfsOfBullets();
1475 SwPosition
aPos(rNd
);
1476 OUString
aPicBullets("_PictureBullets");
1477 AppendBookmark(aPicBullets
);
1478 for (int i
= 0; i
< nCount
; i
++)
1480 sw::Frame
aFrame(*(m_vecBulletPic
[i
]), aPos
);
1481 OutGrfBullets(aFrame
);
1483 AppendBookmark(aPicBullets
);
1487 static sal_uInt8 nAttrMagicIdx
= 0;
1488 void WW8Export::OutGrfBullets(const sw::Frame
& rFrame
)
1490 if ( !pGrf
|| !pChpPlc
|| !pO
)
1493 pGrf
->Insert(rFrame
);
1494 pChpPlc
->AppendFkpEntry( Strm().Tell(), pO
->size(), pO
->data() );
1497 WriteChar( (char)1 );
1499 sal_uInt8 aArr
[ 22 ];
1500 sal_uInt8
* pArr
= aArr
;
1504 Set_UInt16( pArr
, 0x855 );
1506 Set_UInt8( pArr
, 117 );
1507 Set_UInt8( pArr
, 1 );
1509 Set_UInt16( pArr
, 0x083c );
1510 Set_UInt8( pArr
, 0x81 );
1514 Set_UInt16( pArr
, 0x6a03 );
1517 Set_UInt8( pArr
, 68 );
1518 Set_UInt8( pArr
, 4 );
1520 Set_UInt32( pArr
, GRF_MAGIC_321
);
1522 //extern nAttrMagicIdx;
1524 Set_UInt8( pArr
, nAttrMagicIdx
++ );
1525 pChpPlc
->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr
- aArr
), aArr
);
1528 int MSWordExportBase::GetGrfIndex(const SvxBrushItem
& rBrush
)
1531 if ( rBrush
.GetGraphic() )
1533 for (unsigned i
= 0; i
< m_vecBulletPic
.size(); ++i
)
1535 if (m_vecBulletPic
[i
]->GetChecksum() == rBrush
.GetGraphic()->GetChecksum())
1546 void MSWordExportBase::AppendWordBookmark( const String
& rName
)
1548 AppendBookmark( BookmarkToWord( rName
) );
1552 //--------------------------------------------------------------------------
1554 void WW8_WrtRedlineAuthor::Write( Writer
& rWrt
)
1556 WW8Export
& rWW8Wrt
= *(((SwWW8Writer
&)rWrt
).m_pExport
);
1557 rWW8Wrt
.WriteAsStringTable(maAuthors
, rWW8Wrt
.pFib
->fcSttbfRMark
,
1558 rWW8Wrt
.pFib
->lcbSttbfRMark
, rWW8Wrt
.bWrtWW8
? 0 : 2);
1561 sal_uInt16
WW8Export::AddRedlineAuthor( sal_uInt16 nId
)
1565 pRedlAuthors
= new WW8_WrtRedlineAuthor
;
1566 pRedlAuthors
->AddName(OUString("Unknown"));
1568 return pRedlAuthors
->AddName( SW_MOD()->GetRedlineAuthor( nId
) );
1571 //--------------------------------------------------------------------------
1573 void WW8Export::WriteAsStringTable(const std::vector
<OUString
>& rStrings
,
1574 sal_Int32
& rfcSttbf
, sal_Int32
& rlcbSttbf
, sal_uInt16 nExtraLen
)
1576 sal_uInt16 n
, nCount
= static_cast< sal_uInt16
>(rStrings
.size());
1579 // we have some Redlines found in the document -> the
1580 // Author Name Stringtable
1581 SvStream
& rStrm
= bWrtWW8
? *pTableStrm
: Strm();
1582 rfcSttbf
= rStrm
.Tell();
1585 SwWW8Writer::WriteShort( rStrm
, -1 );
1586 SwWW8Writer::WriteLong( rStrm
, nCount
);
1587 for( n
= 0; n
< nCount
; ++n
)
1589 const String
& rNm
= rStrings
[n
];
1590 SwWW8Writer::WriteShort( rStrm
, rNm
.Len() );
1591 SwWW8Writer::WriteString16(rStrm
, rNm
, false);
1593 SwWW8Writer::FillCount(rStrm
, nExtraLen
);
1598 SwWW8Writer::WriteShort( rStrm
, 0 );
1599 for( n
= 0; n
< nCount
; ++n
)
1601 const OUString
&rString
= rStrings
[n
];
1602 const String
aNm(rString
.copy(0, std::min
<sal_Int32
>(rString
.getLength(), 255)));
1603 rStrm
<< (sal_uInt8
)aNm
.Len();
1604 SwWW8Writer::WriteString8(rStrm
, aNm
, false,
1605 RTL_TEXTENCODING_MS_1252
);
1607 SwWW8Writer::FillCount(rStrm
, nExtraLen
);
1610 rlcbSttbf
= rStrm
.Tell() - rfcSttbf
;
1612 SwWW8Writer::WriteShort( rStrm
, rfcSttbf
, (sal_uInt16
)rlcbSttbf
);
1616 // WriteShort() traegt an FilePos nPos den Wert nVal ein und seekt auf die
1617 // alte FilePos zurueck. Benutzt zum Nachtragen von Laengen.
1618 void SwWW8Writer::WriteShort( SvStream
& rStrm
, sal_uLong nPos
, sal_Int16 nVal
)
1620 sal_uLong nOldPos
= rStrm
.Tell(); // remember Pos
1622 SwWW8Writer::WriteShort( rStrm
, nVal
);
1623 rStrm
.Seek( nOldPos
);
1626 void SwWW8Writer::WriteLong( SvStream
& rStrm
, sal_uLong nPos
, sal_Int32 nVal
)
1628 sal_uLong nOldPos
= rStrm
.Tell(); // remember Pos
1630 SwWW8Writer::WriteLong( rStrm
, nVal
);
1631 rStrm
.Seek( nOldPos
);
1634 void SwWW8Writer::InsUInt16(ww::bytes
&rO
, sal_uInt16 n
)
1637 ShortToSVBT16( n
, nL
);
1638 rO
.push_back(nL
[0]);
1639 rO
.push_back(nL
[1]);
1642 void SwWW8Writer::InsUInt32(ww::bytes
&rO
, sal_uInt32 n
)
1645 UInt32ToSVBT32( n
, nL
);
1646 rO
.push_back(nL
[0]);
1647 rO
.push_back(nL
[1]);
1648 rO
.push_back(nL
[2]);
1649 rO
.push_back(nL
[3]);
1652 void SwWW8Writer::InsAsString16(ww::bytes
&rO
, const String
& rStr
)
1654 const sal_Unicode
* pStr
= rStr
.GetBuffer();
1655 for( xub_StrLen n
= 0, nLen
= rStr
.Len(); n
< nLen
; ++n
, ++pStr
)
1656 SwWW8Writer::InsUInt16( rO
, *pStr
);
1659 void SwWW8Writer::InsAsString8(ww::bytes
&rO
, const String
& rStr
,
1660 rtl_TextEncoding eCodeSet
)
1662 OString
sTmp(OUStringToOString(rStr
, eCodeSet
));
1663 const sal_Char
*pStart
= sTmp
.getStr();
1664 const sal_Char
*pEnd
= pStart
+ sTmp
.getLength();
1665 rO
.reserve(rO
.size() + sTmp
.getLength());
1667 std::copy(pStart
, pEnd
, std::inserter(rO
, rO
.end()));
1670 void SwWW8Writer::WriteString16(SvStream
& rStrm
, const String
& rStr
,
1674 SwWW8Writer::InsAsString16(aBytes
, rStr
);
1676 SwWW8Writer::InsUInt16(aBytes
, 0);
1677 //vectors are guaranteed to have contiguous memory, so we can do
1678 //this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1679 if (!aBytes
.empty())
1680 rStrm
.Write(&aBytes
[0], aBytes
.size());
1683 void SwWW8Writer::WriteString_xstz(SvStream
& rStrm
, const String
& rStr
, bool bAddZero
)
1686 SwWW8Writer::InsUInt16(aBytes
, rStr
.Len());
1687 SwWW8Writer::InsAsString16(aBytes
, rStr
);
1689 SwWW8Writer::InsUInt16(aBytes
, 0);
1690 rStrm
.Write(&aBytes
[0], aBytes
.size());
1694 void SwWW8Writer::WriteString8(SvStream
& rStrm
, const String
& rStr
,
1695 bool bAddZero
, rtl_TextEncoding eCodeSet
)
1698 SwWW8Writer::InsAsString8(aBytes
, rStr
, eCodeSet
);
1700 aBytes
.push_back(0);
1701 //vectors are guaranteed to have contiguous memory, so we can do
1702 ////this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1703 if (!aBytes
.empty())
1704 rStrm
.Write(&aBytes
[0], aBytes
.size());
1707 void WW8Export::WriteStringAsPara( const String
& rTxt
, sal_uInt16 nStyleId
)
1710 OutSwString( rTxt
, 0, rTxt
.Len(), IsUnicode(), RTL_TEXTENCODING_MS_1252
);
1711 WriteCR(); // CR thereafter
1714 SwWW8Writer::InsUInt16( aArr
, nStyleId
);
1719 SwWW8Writer::InsUInt16( aArr
, NS_sprm::LN_PFInTable
);
1721 aArr
.push_back( 24 );
1722 aArr
.push_back( 1 );
1725 sal_uLong nPos
= Strm().Tell();
1726 pPapPlc
->AppendFkpEntry( nPos
, aArr
.size(), aArr
.data() );
1727 pChpPlc
->AppendFkpEntry( nPos
);
1730 void MSWordExportBase::WriteSpecialText( sal_uLong nStart
, sal_uLong nEnd
, sal_uInt8 nTTyp
)
1732 sal_uInt8 nOldTyp
= nTxtTyp
;
1734 SwPaM
* pOldPam
= pCurPam
; //!! Simply shifting the PaM without restoring should do the job too
1735 SwPaM
* pOldEnd
= pOrigPam
;
1736 bool bOldPageDescs
= bOutPageDescs
;
1737 bOutPageDescs
= false;
1738 // bOutKF was setted / stored in WriteKF1
1739 pCurPam
= Writer::NewSwPaM( *pDoc
, nStart
, nEnd
);
1741 // Tabelle in Sonderbereichen erkennen
1742 if ( ( nStart
!= pCurPam
->GetMark()->nNode
.GetIndex() ) &&
1743 pDoc
->GetNodes()[ nStart
]->IsTableNode() )
1745 pCurPam
->GetMark()->nNode
= nStart
;
1749 pCurPam
->Exchange();
1753 bOutPageDescs
= bOldPageDescs
;
1754 delete pCurPam
; // delete Pam
1760 void WW8Export::OutSwString(const String
& rStr
, xub_StrLen nStt
,
1761 xub_StrLen nLen
, bool bUnicode
, rtl_TextEncoding eChrSet
)
1764 SAL_INFO( "sw.ww8.level2", "<OutSwString>" );
1768 if ( bUnicode
!= pPiece
->IsUnicode() )
1769 pPiece
->AppendPc ( Strm().Tell(), bUnicode
);
1771 if( nStt
|| nLen
!= rStr
.Len() )
1773 String
sOut( rStr
.Copy( nStt
, nLen
) );
1775 SAL_INFO( "sw.ww8.level2", sOut
);
1778 SwWW8Writer::WriteString16(Strm(), sOut
, false);
1780 SwWW8Writer::WriteString8(Strm(), sOut
, false, eChrSet
);
1784 SAL_INFO( "sw.ww8.level2", rStr
);
1787 SwWW8Writer::WriteString16(Strm(), rStr
, false);
1789 SwWW8Writer::WriteString8(Strm(), rStr
, false, eChrSet
);
1793 SAL_INFO( "sw.ww8.level2", "</OutSwString>" );
1796 void WW8Export::WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1798 if (pTableTextNodeInfoInner
.get() != NULL
&& pTableTextNodeInfoInner
->getDepth() == 1 && pTableTextNodeInfoInner
->isEndOfCell())
1801 WriteChar( '\015' );
1803 pPiece
->SetParaBreak();
1806 void WW8Export::WriteChar( sal_Unicode c
)
1808 if( pPiece
->IsUnicode() )
1811 Strm() << (sal_uInt8
)c
;
1814 void MSWordExportBase::SaveData( sal_uLong nStt
, sal_uLong nEnd
)
1816 MSWordSaveData aData
;
1818 // WW8Export only stuff - zeroed here not to issue warnings
1822 aData
.pOldPam
= pCurPam
;
1823 aData
.pOldEnd
= pOrigPam
;
1824 aData
.pOldFlyFmt
= mpParentFrame
;
1825 aData
.pOldPageDesc
= pAktPageDesc
;
1827 aData
.pOldFlyOffset
= pFlyOffset
;
1828 aData
.eOldAnchorType
= eNewAnchorType
;
1830 aData
.bOldOutTable
= bOutTable
;
1831 aData
.bOldFlyFrmAttrs
= bOutFlyFrmAttrs
;
1832 aData
.bOldStartTOX
= bStartTOX
;
1833 aData
.bOldInWriteTOX
= bInWriteTOX
;
1835 pCurPam
= Writer::NewSwPaM( *pDoc
, nStt
, nEnd
);
1837 // Recognize tables in special cases
1838 if ( nStt
!= pCurPam
->GetMark()->nNode
.GetIndex() &&
1839 pDoc
->GetNodes()[ nStt
]->IsTableNode() )
1841 pCurPam
->GetMark()->nNode
= nStt
;
1845 pCurPam
->Exchange();
1848 // Caution: bIsInTable should not be set here
1849 bOutFlyFrmAttrs
= false;
1851 bInWriteTOX
= false;
1853 maSaveData
.push( aData
);
1856 void MSWordExportBase::RestoreData()
1858 MSWordSaveData
&rData
= maSaveData
.top();
1861 pCurPam
= rData
.pOldPam
;
1862 pOrigPam
= rData
.pOldEnd
;
1864 bOutTable
= rData
.bOldOutTable
;
1865 bOutFlyFrmAttrs
= rData
.bOldFlyFrmAttrs
;
1866 bStartTOX
= rData
.bOldStartTOX
;
1867 bInWriteTOX
= rData
.bOldInWriteTOX
;
1869 mpParentFrame
= rData
.pOldFlyFmt
;
1870 pAktPageDesc
= rData
.pOldPageDesc
;
1872 eNewAnchorType
= rData
.eOldAnchorType
;
1873 pFlyOffset
= rData
.pOldFlyOffset
;
1878 void WW8Export::SaveData( sal_uLong nStt
, sal_uLong nEnd
)
1880 MSWordExportBase::SaveData( nStt
, nEnd
);
1882 MSWordSaveData
&rData
= maSaveData
.top();
1887 pO
= new ww::bytes();
1890 rData
.pOOld
= 0; // reuse pO
1892 rData
.bOldWriteAll
= GetWriter().bWriteAll
;
1893 GetWriter().bWriteAll
= true;
1896 void WW8Export::RestoreData()
1898 MSWordSaveData
&rData
= maSaveData
.top();
1900 GetWriter().bWriteAll
= rData
.bOldWriteAll
;
1902 OSL_ENSURE( pO
->empty(), "pO is not empty in WW8Export::RestoreData()" );
1909 MSWordExportBase::RestoreData();
1912 void WW8AttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1914 sal_uInt32 nDepth
= pTableTextNodeInfoInner
->getDepth();
1919 m_rWW8Export
.InsUInt16( NS_sprm::LN_PFInTable
);
1920 m_rWW8Export
.pO
->push_back( (sal_uInt8
)0x1 );
1921 m_rWW8Export
.InsUInt16( NS_sprm::LN_PTableDepth
);
1922 m_rWW8Export
.InsUInt32( nDepth
);
1924 if ( nDepth
> 1 && pTableTextNodeInfoInner
->isEndOfCell() )
1926 m_rWW8Export
.InsUInt16( NS_sprm::LN_PCell
);
1927 m_rWW8Export
.pO
->push_back( (sal_uInt8
)0x1 );
1932 void WW8AttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1934 sal_uInt32 nDepth
= pTableTextNodeInfoInner
->getDepth();
1939 if ( pTableTextNodeInfoInner
->isEndOfLine() )
1941 m_rWW8Export
.InsUInt16( NS_sprm::LN_PFInTable
);
1942 m_rWW8Export
.pO
->push_back( (sal_uInt8
)0x1 );
1946 m_rWW8Export
.InsUInt16( NS_sprm::LN_PFTtp
);
1947 m_rWW8Export
.pO
->push_back( (sal_uInt8
)0x1 );
1950 m_rWW8Export
.InsUInt16( NS_sprm::LN_PTableDepth
);
1951 m_rWW8Export
.InsUInt32( nDepth
);
1955 m_rWW8Export
.InsUInt16( NS_sprm::LN_PCell
);
1956 m_rWW8Export
.pO
->push_back( (sal_uInt8
)0x1 );
1957 m_rWW8Export
.InsUInt16( NS_sprm::LN_PRow
);
1958 m_rWW8Export
.pO
->push_back( (sal_uInt8
)0x1 );
1961 TableDefinition( pTableTextNodeInfoInner
);
1962 TableHeight( pTableTextNodeInfoInner
);
1963 TableBackgrounds( pTableTextNodeInfoInner
);
1964 TableDefaultBorders( pTableTextNodeInfoInner
);
1965 TableCanSplit( pTableTextNodeInfoInner
);
1966 TableBidi( pTableTextNodeInfoInner
);
1967 TableVerticalCell( pTableTextNodeInfoInner
);
1968 TableOrientation( pTableTextNodeInfoInner
);
1969 TableSpacing( pTableTextNodeInfoInner
);
1974 static sal_uInt16
lcl_TCFlags(SwDoc
&rDoc
, const SwTableBox
* pBox
, sal_Int32 nRowSpan
)
1976 sal_uInt16 nFlags
= 0;
1980 else if (nRowSpan
< 0)
1985 const SwFrmFmt
* pFmt
= pBox
->GetFrmFmt();
1986 switch (pFmt
->GetVertOrient().GetVertOrient())
1988 case text::VertOrientation::CENTER
:
1991 case text::VertOrientation::BOTTOM
:
1997 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
2000 SwNodeIndex
aIdx( *pSttNd
);
2001 const SwCntntNode
* pCNd
= pSttNd
->GetNodes().GoNext( &aIdx
);
2002 if( pCNd
&& pCNd
->IsTxtNode())
2004 SfxItemSet
aCoreSet(rDoc
.GetAttrPool(), RES_CHRATR_ROTATE
, RES_CHRATR_ROTATE
);
2005 ((SwTxtNode
*)pCNd
)->GetAttr( aCoreSet
, 0, ((SwTxtNode
*)pCNd
)->GetTxt().getLength());
2006 const SvxCharRotateItem
* pRotate
= NULL
;
2007 const SfxPoolItem
* pRotItem
;
2008 if ( SFX_ITEM_SET
== aCoreSet
.GetItemState(RES_CHRATR_ROTATE
, sal_True
, &pRotItem
))
2010 pRotate
= (SvxCharRotateItem
*)pRotItem
;
2011 if(pRotate
&& pRotate
->GetValue() == 900)
2013 nFlags
= nFlags
| 0x0004 | 0x0008;
2015 else if(pRotate
&& pRotate
->GetValue() == 2700 )
2017 nFlags
= nFlags
| 0x0004 | 0x0010;
2027 void WW8AttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2029 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
2030 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
2031 const SwTableBoxes
& rTblBoxes
= pTabLine
->GetTabBoxes();
2033 sal_uInt8 nBoxes
= rTblBoxes
.size();
2034 for ( sal_uInt8 n
= 0; n
< nBoxes
; n
++ )
2036 const SwTableBox
* pTabBox1
= rTblBoxes
[n
];
2037 const SwFrmFmt
* pFrmFmt
= pTabBox1
->GetFrmFmt();
2039 if ( FRMDIR_VERT_TOP_RIGHT
== m_rWW8Export
.TrueFrameDirection( *pFrmFmt
) )
2041 m_rWW8Export
.InsUInt16( NS_sprm::LN_TTextFlow
);
2042 m_rWW8Export
.pO
->push_back( sal_uInt8(n
) ); //start range
2043 m_rWW8Export
.pO
->push_back( sal_uInt8(n
+ 1) ); //end range
2044 m_rWW8Export
.InsUInt16( 5 ); //Equals vertical writing
2049 void WW8AttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2051 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
2052 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
2053 const SwFrmFmt
* pLineFmt
= pTabLine
->GetFrmFmt();
2056 By default the row can be split in word, and now in writer we have a
2057 feature equivalent to this, Word stores 1 for fCantSplit if the row
2058 cannot be split, we set true if we can split it. An example is #i4569#
2061 const SwFmtRowSplit
& rSplittable
= pLineFmt
->GetRowSplit();
2062 sal_uInt8 nCantSplit
= (!rSplittable
.GetValue()) ? 1 : 0;
2063 if ( m_rWW8Export
.bWrtWW8
)
2065 m_rWW8Export
.InsUInt16( NS_sprm::LN_TFCantSplit
);
2066 m_rWW8Export
.pO
->push_back( nCantSplit
);
2067 m_rWW8Export
.InsUInt16( NS_sprm::LN_TFCantSplit90
); // also write fCantSplit90
2071 m_rWW8Export
.pO
->push_back( 185 );
2073 m_rWW8Export
.pO
->push_back( nCantSplit
);
2076 void WW8AttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2078 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
2079 const SwFrmFmt
* pFrmFmt
= pTable
->GetFrmFmt();
2081 if ( m_rWW8Export
.bWrtWW8
)
2083 if ( m_rWW8Export
.TrueFrameDirection(*pFrmFmt
) == FRMDIR_HORI_RIGHT_TOP
)
2085 m_rWW8Export
.InsUInt16( NS_sprm::LN_TFBiDi
);
2086 m_rWW8Export
.InsUInt16( 1 );
2091 void WW8AttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2093 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
2094 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
2095 const SwFrmFmt
* pLineFmt
= pTabLine
->GetFrmFmt();
2097 // Zeilenhoehe ausgeben sprmTDyaRowHeight
2099 const SwFmtFrmSize
& rLSz
= pLineFmt
->GetFrmSize();
2100 if ( ATT_VAR_SIZE
!= rLSz
.GetHeightSizeType() && rLSz
.GetHeight() )
2102 if ( ATT_MIN_SIZE
== rLSz
.GetHeightSizeType() )
2103 nHeight
= rLSz
.GetHeight();
2105 nHeight
= -rLSz
.GetHeight();
2110 if ( m_rWW8Export
.bWrtWW8
)
2111 m_rWW8Export
.InsUInt16( NS_sprm::LN_TDyaRowHeight
);
2113 m_rWW8Export
.pO
->push_back( 189 );
2114 m_rWW8Export
.InsUInt16( (sal_uInt16
)nHeight
);
2119 void WW8AttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2121 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
2123 const SwFrmFmt
*pFmt
= pTable
->GetFrmFmt();
2124 OSL_ENSURE(pFmt
,"Impossible");
2128 const SwFmtHoriOrient
&rHori
= pFmt
->GetHoriOrient();
2129 const SwFmtVertOrient
&rVert
= pFmt
->GetVertOrient();
2132 (text::RelOrientation::PRINT_AREA
== rHori
.GetRelationOrient() ||
2133 text::RelOrientation::FRAME
== rHori
.GetRelationOrient())
2135 (text::RelOrientation::PRINT_AREA
== rVert
.GetRelationOrient() ||
2136 text::RelOrientation::FRAME
== rVert
.GetRelationOrient())
2139 sal_Int16 eHOri
= rHori
.GetHoriOrient();
2142 case text::HoriOrientation::CENTER
:
2143 case text::HoriOrientation::RIGHT
:
2144 if ( m_rWW8Export
.bWrtWW8
)
2145 m_rWW8Export
.InsUInt16( NS_sprm::LN_TJc
);
2147 m_rWW8Export
.pO
->push_back( 182 );
2148 m_rWW8Export
.InsUInt16( text::HoriOrientation::RIGHT
== eHOri
? 2 : 1 );
2156 void WW8AttributeOutput::TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2158 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
2159 const SwTableFmt
* pTableFmt
= pTable
->GetTableFmt();
2161 // Writing these SPRM's will make the table a floating one, so only write
2162 // them in case the table is already inside a frame.
2163 if (pTableFmt
!= NULL
&& pTable
->GetTableNode()->GetFlyFmt())
2165 const SvxULSpaceItem
& rUL
= pTableFmt
->GetULSpace();
2167 if (rUL
.GetUpper() > 0)
2169 sal_uInt8 nPadding
= 2;
2170 sal_uInt8 nPcVert
= 0;
2171 sal_uInt8 nPcHorz
= 0;
2173 sal_uInt8 nTPc
= (nPadding
<< 4) | (nPcVert
<< 2) | nPcHorz
;
2175 m_rWW8Export
.InsUInt16(NS_sprm::LN_TPc
);
2176 m_rWW8Export
.pO
->push_back( nTPc
);
2178 m_rWW8Export
.InsUInt16(NS_sprm::LN_TDyaAbs
);
2179 m_rWW8Export
.InsUInt16(rUL
.GetUpper());
2181 m_rWW8Export
.InsUInt16(NS_sprm::LN_TDyaFromText
);
2182 m_rWW8Export
.InsUInt16(rUL
.GetUpper());
2185 if (rUL
.GetLower() > 0)
2187 m_rWW8Export
.InsUInt16(NS_sprm::LN_TDyaFromTextBottom
);
2188 m_rWW8Export
.InsUInt16(rUL
.GetLower());
2193 void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2195 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
2197 if ( pTable
->GetRowsToRepeat() > pTableTextNodeInfoInner
->getRow() )
2199 if( m_rWW8Export
.bWrtWW8
)
2200 m_rWW8Export
.InsUInt16( NS_sprm::LN_TTableHeader
);
2202 m_rWW8Export
.pO
->push_back( 186 );
2203 m_rWW8Export
.pO
->push_back( 1 );
2206 ww8::TableBoxVectorPtr pTableBoxes
=
2207 pTableTextNodeInfoInner
->getTableBoxesOfRow();
2208 // number of cell written
2209 sal_uInt32 nBoxes
= pTableBoxes
->size();
2210 if (nBoxes
> ww8::MAXTABLECELLS
)
2211 nBoxes
= ww8::MAXTABLECELLS
;
2214 m_rWW8Export
.InsUInt16( NS_sprm::LN_TDefTable
);
2215 sal_uInt16 nSprmSize
= 2 + (nBoxes
+ 1) * 2 + nBoxes
* 20;
2216 m_rWW8Export
.InsUInt16( nSprmSize
); // length
2219 m_rWW8Export
.pO
->push_back( static_cast<sal_uInt8
>(nBoxes
) );
2223 ALWAYS relative when text::HoriOrientation::NONE (nPageSize + ( nPageSize / 10 )) < nTblSz,
2224 in that case the cell width's and table width's are not real. The table
2225 width is maxed and cells relative, so we need the frame (generally page)
2226 width that the table is in to work out the true widths.
2228 //const bool bNewTableModel = pTbl->IsNewModel();
2229 const SwFrmFmt
*pFmt
= pTable
->GetFrmFmt();
2230 OSL_ENSURE(pFmt
,"Impossible");
2234 const SwFmtHoriOrient
&rHori
= pFmt
->GetHoriOrient();
2235 const SwFmtVertOrient
&rVert
= pFmt
->GetVertOrient();
2237 sal_uInt16 nTblOffset
= 0;
2240 (text::RelOrientation::PRINT_AREA
== rHori
.GetRelationOrient() ||
2241 text::RelOrientation::FRAME
== rHori
.GetRelationOrient())
2243 (text::RelOrientation::PRINT_AREA
== rVert
.GetRelationOrient() ||
2244 text::RelOrientation::FRAME
== rVert
.GetRelationOrient())
2247 sal_Int16 eHOri
= rHori
.GetHoriOrient();
2250 case text::HoriOrientation::CENTER
:
2251 case text::HoriOrientation::RIGHT
:
2255 nTblOffset
= rHori
.GetPos();
2256 const SvxLRSpaceItem
& rLRSp
= pFmt
->GetLRSpace();
2257 nTblOffset
+= rLRSp
.GetLeft();
2262 m_rWW8Export
.InsUInt16( nTblOffset
);
2264 ww8::GridColsPtr pGridCols
= GetGridCols( pTableTextNodeInfoInner
);
2265 for ( ww8::GridCols::const_iterator it
= pGridCols
->begin(),
2266 end
= pGridCols
->end(); it
!= end
; ++it
)
2268 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>( *it
) + nTblOffset
);
2272 ww8::RowSpansPtr pRowSpans
= pTableTextNodeInfoInner
->getRowSpansOfRow();
2273 ww8::RowSpans::const_iterator aItRowSpans
= pRowSpans
->begin();
2274 ww8::TableBoxVector::const_iterator aIt
;
2275 ww8::TableBoxVector::const_iterator aItEnd
= pTableBoxes
->end();
2277 #if OSL_DEBUG_LEVEL > 1
2278 size_t nRowSpans
= pRowSpans
->size();
2279 size_t nTableBoxes
= pTableBoxes
->size();
2284 for( aIt
= pTableBoxes
->begin(); aIt
!= aItEnd
; ++aIt
, ++aItRowSpans
)
2286 sal_uInt16 npOCount
= m_rWW8Export
.pO
->size();
2288 const SwTableBox
* pTabBox1
= *aIt
;
2289 const SwFrmFmt
* pBoxFmt
= NULL
;
2290 if (pTabBox1
!= NULL
)
2291 pBoxFmt
= pTabBox1
->GetFrmFmt();
2293 if ( m_rWW8Export
.bWrtWW8
)
2296 lcl_TCFlags(*m_rWW8Export
.pDoc
, pTabBox1
, *aItRowSpans
);
2297 m_rWW8Export
.InsUInt16( nFlags
);
2300 static sal_uInt8 aNullBytes
[] = { 0x0, 0x0 };
2302 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), aNullBytes
, aNullBytes
+2 ); // dummy
2303 if (pBoxFmt
!= NULL
)
2305 const SvxBoxItem
& rBoxItem
= pBoxFmt
->GetBox();
2307 m_rWW8Export
.Out_SwFmtTableBox( *m_rWW8Export
.pO
, &rBoxItem
); // 8/16 Byte
2310 m_rWW8Export
.Out_SwFmtTableBox( *m_rWW8Export
.pO
, NULL
); // 8/16 Byte
2312 SAL_INFO( "sw.ww8.level2", "<tclength>" << ( m_rWW8Export
.pO
->size() - npOCount
) << "</tclength>" );
2316 ww8::GridColsPtr
AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2318 return pTableTextNodeInfoInner
->getGridColsOfRow(*this);
2321 void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner
* pTableTextNodeInfoInner
, sal_uInt32
& rPageSize
, bool& rRelBoxSize
)
2323 sal_uInt32 nPageSize
= 0;
2325 const SwNode
*pTxtNd
= pTableTextNodeInfoInner
->getNode( );
2326 const SwTable
*pTable
= pTableTextNodeInfoInner
->getTable( );
2328 const SwFrmFmt
*pFmt
= pTable
->GetFrmFmt();
2329 OSL_ENSURE(pFmt
,"Impossible");
2333 const SwFmtFrmSize
&rSize
= pFmt
->GetFrmSize();
2334 int nWidthPercent
= rSize
.GetWidthPercent();
2335 bool bManualAligned
= pFmt
->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::NONE
;
2336 if ( (pFmt
->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::FULL
) || bManualAligned
)
2337 nWidthPercent
= 100;
2338 bool bRelBoxSize
= nWidthPercent
!= 0;
2339 unsigned long nTblSz
= static_cast<unsigned long>(rSize
.GetWidth());
2340 if (nTblSz
> USHRT_MAX
/2 && !bRelBoxSize
)
2342 OSL_ENSURE(bRelBoxSize
, "huge table width but not relative, suspicious");
2349 SwRect
aRect( pFmt
->FindLayoutRect( false, &aPt
) );
2350 if ( aRect
.IsEmpty() )
2352 // dann besorge mal die Seitenbreite ohne Raender !!
2353 const SwFrmFmt
* pParentFmt
=
2354 GetExport().mpParentFrame
?
2355 &(GetExport().mpParentFrame
->GetFrmFmt()) :
2356 GetExport().pDoc
->GetPageDesc(0).GetPageFmtOfNode(*pTxtNd
, false);
2357 aRect
= pParentFmt
->FindLayoutRect(true);
2358 if ( 0 == ( nPageSize
= aRect
.Width() ) )
2360 const SvxLRSpaceItem
& rLR
= pParentFmt
->GetLRSpace();
2361 nPageSize
= pParentFmt
->GetFrmSize().GetWidth() - rLR
.GetLeft()
2367 nPageSize
= aRect
.Width();
2368 if ( bManualAligned
)
2370 // #i37571# For manually aligned tables
2371 const SvxLRSpaceItem
&rLR
= pFmt
->GetLRSpace();
2372 nPageSize
-= (rLR
.GetLeft() + rLR
.GetRight());
2377 OSL_ENSURE(nWidthPercent
, "Impossible");
2380 nPageSize
*= nWidthPercent
;
2385 rPageSize
= nPageSize
;
2386 rRelBoxSize
= bRelBoxSize
;
2389 void WW8AttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2391 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
2392 const SwFrmFmt
* pFrmFmt
= pTabBox
->GetFrmFmt();
2394 //Set Default, just taken from the first cell of the first
2396 static sal_uInt16 aBorders
[] =
2398 BOX_LINE_TOP
, BOX_LINE_LEFT
,
2399 BOX_LINE_BOTTOM
, BOX_LINE_RIGHT
2402 for ( int i
= 0; i
< 4; ++i
)
2404 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, 0xD634 );
2405 m_rWW8Export
.pO
->push_back( sal_uInt8(6) );
2406 m_rWW8Export
.pO
->push_back( sal_uInt8(0) );
2407 m_rWW8Export
.pO
->push_back( sal_uInt8(1) );
2408 m_rWW8Export
.pO
->push_back( sal_uInt8(1 << i
) );
2409 m_rWW8Export
.pO
->push_back( sal_uInt8(3) );
2411 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
,
2412 pFrmFmt
->GetBox().GetDistance( aBorders
[i
] ) );
2416 void WW8AttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2418 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
2419 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
2420 const SwTableBoxes
& rTabBoxes
= pTabLine
->GetTabBoxes();
2422 sal_uInt8 nBoxes
= rTabBoxes
.size();
2423 if ( m_rWW8Export
.bWrtWW8
)
2424 m_rWW8Export
.InsUInt16( NS_sprm::LN_TDefTableShd
);
2426 m_rWW8Export
.pO
->push_back( (sal_uInt8
)191 );
2427 m_rWW8Export
.pO
->push_back( (sal_uInt8
)(nBoxes
* 2) ); // Len
2429 for ( sal_uInt8 n
= 0; n
< nBoxes
; n
++ )
2431 const SwTableBox
* pBox1
= rTabBoxes
[n
];
2432 const SwFrmFmt
* pFrmFmt
= pBox1
->GetFrmFmt();
2433 const SfxPoolItem
* pI
= NULL
;
2436 if ( SFX_ITEM_ON
== pFrmFmt
->GetAttrSet().GetItemState( RES_BACKGROUND
, false, &pI
) )
2438 aColor
= dynamic_cast<const SvxBrushItem
*>(pI
)->GetColor();
2444 m_rWW8Export
.TransBrush( aColor
, aShd
);
2445 m_rWW8Export
.InsUInt16( aShd
.GetValue() );
2448 if ( m_rWW8Export
.bWrtWW8
)
2450 sal_uInt32 aSprmIds
[] = {NS_sprm::LN_TCellShd
, NS_sprm::LN_TCellShadow
};
2451 sal_uInt8 nBoxes0
= rTabBoxes
.size();
2455 for (sal_uInt32 m
= 0; m
< 2; m
++)
2457 m_rWW8Export
.InsUInt16( aSprmIds
[m
] );
2458 m_rWW8Export
.pO
->push_back( static_cast<sal_uInt8
>(nBoxes0
* 10) );
2460 for ( sal_uInt8 n
= 0; n
< nBoxes0
; n
++ )
2462 const SwTableBox
* pBox1
= rTabBoxes
[n
];
2463 const SwFrmFmt
* pFrmFmt
= pBox1
->GetFrmFmt();
2464 const SfxPoolItem
* pI
= NULL
;
2468 pFrmFmt
->GetAttrSet().
2469 GetItemState( RES_BACKGROUND
, false, &pI
) )
2471 aColor
= dynamic_cast<const SvxBrushItem
*>(pI
)->GetColor();
2477 aSHD
.setCvFore( 0xFF000000 );
2479 sal_uInt32 nBgColor
= aColor
.GetColor();
2480 if ( nBgColor
== COL_AUTO
)
2481 aSHD
.setCvBack( 0xFF000000 );
2483 aSHD
.setCvBack( wwUtility::RGBToBGR( nBgColor
) );
2485 aSHD
.Write( m_rWW8Export
);
2491 void WW8Export::SectionBreaksAndFrames( const SwTxtNode
& rNode
)
2493 // output page/section breaks
2494 OutputSectionBreaks( rNode
.GetpSwAttrSet(), rNode
);
2496 // all textframes anchored as character for the winword 7- format
2497 if ( !bWrtWW8
&& !IsInTable() )
2498 OutWW6FlyFrmsInCntnt( rNode
);
2501 void MSWordExportBase::WriteText()
2503 while( pCurPam
->GetPoint()->nNode
< pCurPam
->GetMark()->nNode
||
2504 ( pCurPam
->GetPoint()->nNode
== pCurPam
->GetMark()->nNode
&&
2505 pCurPam
->GetPoint()->nContent
.GetIndex() <= pCurPam
->GetMark()->nContent
.GetIndex() ) )
2507 SwNode
* pNd
= pCurPam
->GetNode();
2509 if ( pNd
->IsTxtNode() )
2510 SectionBreaksAndFrames( *pNd
->GetTxtNode() );
2512 // output the various types of nodes
2513 if ( pNd
->IsCntntNode() )
2515 SwCntntNode
* pCNd
= (SwCntntNode
*)pNd
;
2517 const SwPageDesc
* pTemp
= pCNd
->GetSwAttrSet().GetPageDesc().GetPageDesc();
2519 pAktPageDesc
= pTemp
;
2521 pCurPam
->GetPoint()->nContent
.Assign( pCNd
, 0 );
2522 OutputContentNode( *pCNd
);
2524 else if ( pNd
->IsTableNode() )
2526 mpTableInfo
->processSwTable( &pNd
->GetTableNode()->GetTable() );
2528 else if ( pNd
->IsSectionNode() && TXT_MAINTEXT
== nTxtTyp
)
2529 OutputSectionNode( *pNd
->GetSectionNode() );
2530 else if ( TXT_MAINTEXT
== nTxtTyp
&& pNd
->IsEndNode() &&
2531 pNd
->StartOfSectionNode()->IsSectionNode() )
2533 const SwSection
& rSect
= pNd
->StartOfSectionNode()->GetSectionNode()
2535 if ( bStartTOX
&& TOX_CONTENT_SECTION
== rSect
.GetType() )
2538 SwNodeIndex
aIdx( *pNd
, 1 );
2539 if ( aIdx
.GetNode().IsEndNode() && aIdx
.GetNode().StartOfSectionNode()->IsSectionNode() )
2541 else if ( aIdx
.GetNode().IsSectionNode() )
2543 else if ( !IsInTable() ) //No sections in table
2545 //#120140# Do not need to insert a page/section break after a section end. Check this case first
2546 sal_Bool bNeedExportBreakHere
= sal_True
;
2547 if ( aIdx
.GetNode().IsTxtNode() )
2549 SwTxtNode
*pTempNext
= aIdx
.GetNode().GetTxtNode();
2552 const SfxPoolItem
* pTempItem
= NULL
;
2553 if (pTempNext
->GetpSwAttrSet() && SFX_ITEM_SET
== pTempNext
->GetpSwAttrSet()->GetItemState(RES_PAGEDESC
, false, &pTempItem
)
2554 && pTempItem
&& ((SwFmtPageDesc
*)pTempItem
)->GetRegisteredIn())
2556 //Next node has a new page style which means this node is a section end. Do not insert another page/section break here
2557 bNeedExportBreakHere
= sal_False
;
2561 if (bNeedExportBreakHere
) //#120140# End of check
2563 ReplaceCr( (char)0xc ); // indicator for Page/Section-Break
2565 const SwSectionFmt
* pParentFmt
= rSect
.GetFmt()->GetParent();
2567 pParentFmt
= (SwSectionFmt
*)0xFFFFFFFF;
2569 sal_uLong nRstLnNum
;
2570 if ( aIdx
.GetNode().IsCntntNode() )
2571 nRstLnNum
= ((SwCntntNode
&)aIdx
.GetNode()).GetSwAttrSet().
2572 GetLineNumber().GetStartValue();
2576 AppendSection( pAktPageDesc
, pParentFmt
, nRstLnNum
);
2580 else if ( pNd
->IsStartNode() )
2582 OutputStartNode( *pNd
->GetStartNode() );
2584 else if ( pNd
->IsEndNode() )
2586 OutputEndNode( *pNd
->GetEndNode() );
2589 if ( pNd
== &pNd
->GetNodes().GetEndOfContent() )
2592 SwNode
* pCurrentNode
= &pCurPam
->GetPoint()->nNode
.GetNode();
2593 const SwNode
* pNextNode
= mpTableInfo
->getNextNode(pCurrentNode
);
2595 if (pNextNode
!= NULL
)
2596 pCurPam
->GetPoint()->nNode
= SwNodeIndex(*pNextNode
);
2598 pCurPam
->GetPoint()->nNode
++;
2600 sal_uLong nPos
= pCurPam
->GetPoint()->nNode
.GetIndex();
2601 ::SetProgressState( nPos
, pCurPam
->GetDoc()->GetDocShell() );
2604 SAL_INFO( "sw.ww8.level2", "</WriteText>" );
2607 void WW8Export::WriteMainText()
2609 SAL_INFO( "sw.ww8.level2", "<WriteMainText>" );
2611 pFib
->fcMin
= Strm().Tell();
2613 pCurPam
->GetPoint()->nNode
= pDoc
->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
2617 if( 0 == Strm().Tell() - pFib
->fcMin
) // no text ?
2618 WriteCR(); // then CR at the end ( otherwise WW will complain )
2620 pFib
->ccpText
= Fc2Cp( Strm().Tell() );
2621 pFldMain
->Finish( pFib
->ccpText
, 0 );
2623 // ccpText includes Footnote and KF-text
2624 // therefore pFib->ccpText may get updated as well
2625 // save the StyleId of the last paragraph. Because WW97 take the style
2626 // from the last CR, that will be writen after footer/Header/footnotes/
2628 const SwTxtNode
* pLastNd
= pCurPam
->GetMark()->nNode
.GetNode().GetTxtNode();
2630 nLastFmtId
= GetId( (SwTxtFmtColl
&)pLastNd
->GetAnyFmtColl() );
2632 SAL_INFO( "sw.ww8.level2", "</WriteMainText>" );
2635 bool MSWordExportBase::IsInTable() const
2637 bool bResult
= false;
2639 if (pCurPam
!= NULL
)
2641 SwNode
* pNode
= pCurPam
->GetNode();
2643 if (pNode
!= NULL
&& mpTableInfo
.get() != NULL
)
2645 ww8::WW8TableNodeInfo::Pointer_t pTableNodeInfo
= mpTableInfo
->getTableNodeInfo(pNode
);
2647 if (pTableNodeInfo
.get() != NULL
&& pTableNodeInfo
->getDepth() > 0)
2657 typedef ww8::WW8Sttb
< ww8::WW8Struct
> WW8SttbAssoc
;
2659 void WW8Export::WriteFkpPlcUsw()
2663 static const sal_uInt8 aSpec
[2] =
2668 pChpPlc
->AppendFkpEntry( Strm().Tell() ); // Sepx with fSpecial
2669 pSepx
->WriteSepx( Strm() ); // Slcx.Sepx
2670 pGrf
->Write(); // Graphics
2671 pChpPlc
->AppendFkpEntry( Strm().Tell(), sizeof( aSpec
), aSpec
);
2673 pChpPlc
->WriteFkps(); // Fkp.Chpx
2674 pPapPlc
->WriteFkps(); // Fkp.Papx
2675 pStyles
->OutputStylesTable(); // Styles
2676 pFtn
->WritePlc( *this ); // Footnote-Ref & Text Plc
2677 pEdn
->WritePlc( *this ); // Endnote-Ref & Text Plc
2678 pAtn
->WritePlc( *this ); // Annotation-Ref & Text Plc
2679 pSepx
->WritePlcSed( *this ); // Slcx.PlcSed
2680 pSepx
->WritePlcHdd( *this ); // Slcx.PlcHdd
2681 pChpPlc
->WritePlc(); // Plcx.Chpx
2682 pPapPlc
->WritePlc(); // Plcx.Papx
2683 maFontHelper
.WriteFontTable(pTableStrm
, *pFib
); // FFNs
2685 pRedlAuthors
->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2686 pFldMain
->Write( *this ); // Fields ( Main Text )
2687 pFldHdFt
->Write( *this ); // Fields ( Header/Footer )
2688 pFldFtn
->Write( *this ); // Fields ( FootNotes )
2689 pFldEdn
->Write( *this ); // Fields ( EndNotes )
2690 pFldAtn
->Write( *this ); // Fields ( Annotations )
2691 pBkmks
->Write( *this ); // Bookmarks - sttbfBkmk/
2692 // plcfBkmkf/plcfBkmkl
2693 WriteDop( *this ); // Document-Properties
2698 // Graphics in the data stream
2699 pGrf
->Write(); // Graphics
2701 // Ausgabe in WordDocument-Stream
2702 pChpPlc
->WriteFkps(); // Fkp.Chpx
2703 pPapPlc
->WriteFkps(); // Fkp.Papx
2704 pSepx
->WriteSepx( Strm() ); // Sepx
2706 // Ausagbe in Table-Stream
2707 pStyles
->OutputStylesTable(); // for WW8 StyleTab
2708 pFtn
->WritePlc( *this ); // Footnote-Ref & Text Plc
2709 pEdn
->WritePlc( *this ); // Endnote-Ref & Text Plc
2710 pTxtBxs
->WritePlc( *this ); // Textbox Text Plc
2711 pHFTxtBxs
->WritePlc( *this ); // Head/Foot-Textbox Text Plc
2712 pAtn
->WritePlc( *this ); // Annotation-Ref & Text Plc
2714 pSepx
->WritePlcSed( *this ); // Slcx.PlcSed
2715 pSepx
->WritePlcHdd( *this ); // Slcx.PlcHdd
2717 pChpPlc
->WritePlc(); // Plcx.Chpx
2718 pPapPlc
->WritePlc(); // Plcx.Papx
2721 pRedlAuthors
->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2722 pFldMain
->Write( *this ); // Fields ( Main Text )
2723 pFldHdFt
->Write( *this ); // Fields ( Header/Footer )
2724 pFldFtn
->Write( *this ); // Fields ( FootNotes )
2725 pFldEdn
->Write( *this ); // Fields ( EndNotes )
2726 pFldAtn
->Write( *this ); // Fields ( Annotations )
2727 pFldTxtBxs
->Write( *this ); // Fields ( Textboxes )
2728 pFldHFTxtBxs
->Write( *this ); // Fields ( Head/Foot-Textboxes )
2730 if (pEscher
|| pDoc
->ContainsMSVBasic())
2733 Everytime MS 2000 creates an escher stream there is always
2734 an ObjectPool dir (even if empty). It turns out that if a copy of
2735 MS 2000 is used to open a document that contains escher graphics
2736 exported from StarOffice without this empty dir then *if* that
2737 copy of MS Office has never been used to open a MSOffice document
2738 that has escher graphics (and an ObjectPool dir of course) and
2739 that copy of office has not been used to draw escher graphics then
2740 our exported graphics do not appear. Once you do open a ms
2741 document with escher graphics or draw an escher graphic with that
2742 copy of word, then all documents from staroffice that contain
2743 escher work from then on. Tricky to track down, some sort of late
2744 binding trickery in MS where solely for first time initialization
2745 the existence of an ObjectPool dir is necessary for triggering
2748 // avoid memory leak #i120098#, the unnamed obj will be released in destructor.
2749 xEscherStg
= GetWriter().GetStorage().OpenSotStorage(OUString(SL::aObjectPool
),
2750 STREAM_READWRITE
| STREAM_SHARE_DENYALL
);
2753 // dggInfo - escher stream
2756 pSdrObjs
->WritePlc( *this );
2757 pHFSdrObjs
->WritePlc( *this );
2758 // spamom - office drawing table
2759 // spahdr - header office drawing table
2761 pBkmks
->Write( *this ); // Bookmarks - sttbfBkmk/
2762 // plcfBkmkf/plcfBkmkl
2768 pMagicTable
->Write( *this );
2770 pPiece
->WritePc( *this ); // Piece-Table
2771 maFontHelper
.WriteFontTable(pTableStrm
, *pFib
); // FFNs
2773 //Convert OOo asian typography into MS typography structure
2774 ExportDopTypography(pDop
->doptypography
);
2776 WriteDop( *this ); // Document-Properties
2779 WW8SttbAssoc
* pSttbfAssoc
= dynamic_cast<WW8SttbAssoc
*>
2780 (pDoc
->getExternalData(::sw::STTBF_ASSOC
).get());
2782 if ( pSttbfAssoc
) // #i106057#
2784 ::std::vector
<OUString
> aStrings
;
2786 ::ww8::StringVector_t
& aSttbStrings
= pSttbfAssoc
->getStrings();
2787 ::ww8::StringVector_t::const_iterator aItEnd
= aSttbStrings
.end();
2788 for (::ww8::StringVector_t::const_iterator aIt
= aSttbStrings
.begin();
2789 aIt
!= aItEnd
; ++aIt
)
2791 aStrings
.push_back(aIt
->getStr());
2794 WriteAsStringTable(aStrings
, pFib
->fcSttbfAssoc
,
2795 pFib
->lcbSttbfAssoc
);
2800 // Reclaim stored FIB data from document.
2801 ::ww8::WW8FibData
* pFibData
= dynamic_cast<ww8::WW8FibData
*>
2802 (pDoc
->getExternalData(::sw::FIB
).get());
2806 pFib
->fReadOnlyRecommended
=
2807 pFibData
->getReadOnlyRecommended() ? 1 : 0;
2808 pFib
->fWriteReservation
=
2809 pFibData
->getWriteReservation() ? 1 : 0;
2812 pFib
->Write( Strm() ); // FIB
2815 void WW8Export::StoreDoc1()
2817 bool bNeedsFinalPara
= false;
2818 // Start of Text ( Mangel ueber )
2819 SwWW8Writer::FillUntil( Strm(), pFib
->fcMin
);
2821 WriteMainText(); // main text
2822 sal_uInt8 nSprmsLen
;
2823 sal_uInt8
*pLastSprms
= pPapPlc
->CopyLastSprms(nSprmsLen
);
2825 bNeedsFinalPara
|= pFtn
->WriteTxt( *this ); // Footnote-Text
2826 bNeedsFinalPara
|= pSepx
->WriteKFTxt( *this ); // K/F-Text
2827 bNeedsFinalPara
|= pAtn
->WriteTxt( *this ); // Annotation-Text
2828 bNeedsFinalPara
|= pEdn
->WriteTxt( *this ); // EndNote-Text
2830 // create the escher streams
2834 bNeedsFinalPara
|= pTxtBxs
->WriteTxt( *this ); //Textbox Text Plc
2835 bNeedsFinalPara
|= pHFTxtBxs
->WriteTxt( *this );//Head/Foot-Textbox Text Plc
2837 if (bNeedsFinalPara
)
2840 pPapPlc
->AppendFkpEntry(Strm().Tell(), nSprmsLen
, pLastSprms
);
2842 delete[] pLastSprms
;
2844 pSepx
->Finish( Fc2Cp( Strm().Tell() ));// Text + Ftn + HdFt als Section-Ende
2845 pMagicTable
->Finish( Fc2Cp( Strm().Tell() ),0);
2847 pFib
->fcMac
= Strm().Tell(); // End of all texts
2849 WriteFkpPlcUsw(); // FKP, PLC, .....
2852 void MSWordExportBase::AddLinkTarget(const String
& rURL
)
2854 if( !rURL
.Len() || rURL
.GetChar(0) != INET_MARK_TOKEN
)
2857 String
aURL( BookmarkToWriter( rURL
.Copy( 1 ) ) );
2858 xub_StrLen nPos
= aURL
.SearchBackward( cMarkSeparator
);
2863 String
sCmp(comphelper::string::remove(aURL
.Copy(nPos
+1), ' '));
2867 sCmp
.ToLowerAscii();
2869 if( sCmp
.EqualsAscii( pMarkToOutline
) )
2871 SwPosition
aPos( *pCurPam
->GetPoint() );
2872 String
aOutline( BookmarkToWriter(aURL
.Copy( 0, nPos
)) );
2873 // If we can find the outline this bookmark refers to
2874 // save the name of the bookmark and the
2875 // node index number of where it points to
2876 if( pDoc
->GotoOutline( aPos
, aOutline
) )
2878 sal_uLong nIdx
= aPos
.nNode
.GetIndex();
2879 aBookmarkPair aImplicitBookmark
;
2880 aImplicitBookmark
.first
= aOutline
;
2881 aImplicitBookmark
.second
= nIdx
;
2882 maImplicitBookmarks
.push_back(aImplicitBookmark
);
2887 void MSWordExportBase::CollectOutlineBookmarks(const SwDoc
&rDoc
)
2889 const SwFmtINetFmt
* pINetFmt
;
2890 const SwTxtINetFmt
* pTxtAttr
;
2891 const SwTxtNode
* pTxtNd
;
2893 sal_uInt32 n
, nMaxItems
= rDoc
.GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT
);
2894 for( n
= 0; n
< nMaxItems
; ++n
)
2896 if( 0 != (pINetFmt
= (SwFmtINetFmt
*)rDoc
.GetAttrPool().GetItem2(
2897 RES_TXTATR_INETFMT
, n
) ) &&
2898 0 != ( pTxtAttr
= pINetFmt
->GetTxtINetFmt()) &&
2899 0 != ( pTxtNd
= pTxtAttr
->GetpTxtNode() ) &&
2900 pTxtNd
->GetNodes().IsDocNodes() )
2902 AddLinkTarget( pINetFmt
->GetValue() );
2906 const SwFmtURL
*pURL
;
2907 nMaxItems
= rDoc
.GetAttrPool().GetItemCount2( RES_URL
);
2908 for( n
= 0; n
< nMaxItems
; ++n
)
2910 if( 0 != (pURL
= (SwFmtURL
*)rDoc
.GetAttrPool().GetItem2(
2913 AddLinkTarget( pURL
->GetURL() );
2914 const ImageMap
*pIMap
= pURL
->GetMap();
2917 for( sal_uInt16 i
=0; i
<pIMap
->GetIMapObjectCount(); i
++ )
2919 const IMapObject
* pObj
= pIMap
->GetIMapObject( i
);
2922 AddLinkTarget( pObj
->GetURL() );
2932 const sal_uLong WW_BLOCKSIZE
= 0x200;
2934 void EncryptRC4(msfilter::MSCodec_Std97
& rCtx
, SvStream
&rIn
, SvStream
&rOut
)
2936 rIn
.Seek(STREAM_SEEK_TO_END
);
2937 sal_uLong nLen
= rIn
.Tell();
2940 sal_uInt8 in
[WW_BLOCKSIZE
];
2941 for (sal_Size nI
= 0, nBlock
= 0; nI
< nLen
; nI
+= WW_BLOCKSIZE
, ++nBlock
)
2943 sal_Size nBS
= (nLen
- nI
> WW_BLOCKSIZE
) ? WW_BLOCKSIZE
: nLen
- nI
;
2944 nBS
= rIn
.Read(in
, nBS
);
2945 rCtx
.InitCipher(nBlock
);
2946 rCtx
.Encode(in
, nBS
, in
, nBS
);
2947 rOut
.Write(in
, nBS
);
2952 void MSWordExportBase::ExportDocument( bool bWriteAll
)
2954 nCharFmtStart
= ANZ_DEFAULT_STYLES
;
2955 nFmtCollStart
= nCharFmtStart
+ pDoc
->GetCharFmts()->size() - 1;
2957 bStyDef
= bBreakBefore
= bOutKF
=
2958 bOutFlyFrmAttrs
= bOutPageDescs
= bOutTable
= bOutFirstPage
=
2959 bOutGrf
= bInWriteEscher
= bStartTOX
=
2960 bInWriteTOX
= false;
2962 bFtnAtTxtEnd
= bEndAtTxtEnd
= true;
2966 eNewAnchorType
= FLY_AT_PAGE
;
2967 nTxtTyp
= TXT_MAINTEXT
;
2968 nStyleBeforeFly
= nLastFmtId
= 0;
2970 pCurrentStyle
= NULL
;
2978 sal_uInt32 nSvxMSDffOLEConvFlags
= 0;
2979 const SvtFilterOptions
& rOpt
= SvtFilterOptions::Get();
2980 if ( rOpt
.IsMath2MathType() )
2981 nSvxMSDffOLEConvFlags
|= OLE_STARMATH_2_MATHTYPE
;
2982 if ( rOpt
.IsWriter2WinWord() )
2983 nSvxMSDffOLEConvFlags
|= OLE_STARWRITER_2_WINWORD
;
2984 if ( rOpt
.IsCalc2Excel() )
2985 nSvxMSDffOLEConvFlags
|= OLE_STARCALC_2_EXCEL
;
2986 if ( rOpt
.IsImpress2PowerPoint() )
2987 nSvxMSDffOLEConvFlags
|= OLE_STARIMPRESS_2_POWERPOINT
;
2989 pOLEExp
= new SvxMSExportOLEObjects( nSvxMSDffOLEConvFlags
);
2992 if ( !pOCXExp
&& pDoc
->GetDocShell() )
2993 pOCXExp
= new SwMSConvertControls( pDoc
->GetDocShell(), pCurPam
);
2995 // #i81405# - Collect anchored objects before changing the redline mode.
2996 maFrames
= GetFrames( *pDoc
, bWriteAll
? NULL
: pOrigPam
);
2998 mnRedlineMode
= pDoc
->GetRedlineMode();
2999 if ( !pDoc
->GetRedlineTbl().empty() )
3001 pDoc
->SetRedlineMode( (RedlineMode_t
)(mnRedlineMode
| nsRedlineMode_t::REDLINE_SHOW_DELETE
|
3002 nsRedlineMode_t::REDLINE_SHOW_INSERT
) );
3005 maFontHelper
.InitFontTable( SupportsUnicode(), *pDoc
);
3006 GatherChapterFields();
3008 CollectOutlineBookmarks(*pDoc
);
3010 // make unique OrdNums (Z-Order) for all drawing-/fly Objects
3011 if ( pDoc
->GetDrawModel() )
3012 pDoc
->GetDrawModel()->GetPage( 0 )->RecalcObjOrdNums();
3014 ExportDocument_Impl();
3016 if ( mnRedlineMode
!= pDoc
->GetRedlineMode() )
3017 pDoc
->SetRedlineMode( (RedlineMode_t
)(mnRedlineMode
) );
3020 bool SwWW8Writer::InitStd97CodecUpdateMedium( ::msfilter::MSCodec_Std97
& rCodec
)
3022 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
3026 SFX_ITEMSET_ARG( mpMedium
->GetItemSet(), pEncryptionDataItem
, SfxUnoAnyItem
, SID_ENCRYPTIONDATA
, sal_False
);
3027 if ( pEncryptionDataItem
&& ( pEncryptionDataItem
->GetValue() >>= aEncryptionData
) && !rCodec
.InitCodec( aEncryptionData
) )
3029 OSL_ENSURE( false, "Unexpected EncryptionData!" );
3030 aEncryptionData
.realloc( 0 );
3033 if ( !aEncryptionData
.getLength() )
3035 // try to generate the encryption data based on password
3036 SFX_ITEMSET_ARG( mpMedium
->GetItemSet(), pPasswordItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
3037 if ( pPasswordItem
&& !pPasswordItem
->GetValue().isEmpty() && pPasswordItem
->GetValue().getLength() <= 15 )
3039 // Generate random number with a seed of time as salt.
3041 osl_getSystemTime( &aTime
);
3042 rtlRandomPool aRandomPool
= rtl_random_createPool ();
3043 rtl_random_addBytes ( aRandomPool
, &aTime
, 8 );
3045 sal_uInt8 pDocId
[ 16 ];
3046 rtl_random_getBytes( aRandomPool
, pDocId
, 16 );
3048 rtl_random_destroyPool( aRandomPool
);
3050 sal_Unicode aPassword
[16];
3051 memset( aPassword
, 0, sizeof( aPassword
) );
3053 OUString
sPassword(pPasswordItem
->GetValue());
3054 for ( sal_Int32 nChar
= 0; nChar
< sPassword
.getLength(); ++nChar
)
3055 aPassword
[nChar
] = sPassword
[nChar
];
3057 rCodec
.InitKey( aPassword
, pDocId
);
3058 aEncryptionData
= rCodec
.GetEncryptionData();
3060 mpMedium
->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
3064 if ( aEncryptionData
.getLength() )
3065 mpMedium
->GetItemSet()->ClearItem( SID_PASSWORD
);
3068 // nonempty encryption data means hier that the codec was successfully initialized
3069 return ( aEncryptionData
.getLength() != 0 );
3072 void WW8Export::ExportDocument_Impl()
3076 pFib
= new WW8Fib( bWrtWW8
? 8 : 6 );
3078 SvStorageStreamRef
xWwStrm( GetWriter().GetStorage().OpenSotStream( aMainStg
) );
3079 SvStorageStreamRef
xTableStrm( xWwStrm
), xDataStrm( xWwStrm
);
3080 xWwStrm
->SetBufferSize( 32768 );
3084 pFib
->fWhichTblStm
= 1;
3085 xTableStrm
= GetWriter().GetStorage().OpenSotStream(OUString(SL::a1Table
),
3087 xDataStrm
= GetWriter().GetStorage().OpenSotStream(OUString(SL::aData
),
3090 xDataStrm
->SetBufferSize( 32768 ); // for graphics
3091 xTableStrm
->SetBufferSize( 16384 ); // for the Font-/Style-Table, etc.
3093 xTableStrm
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
3094 xDataStrm
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
3097 GetWriter().SetStream( & *xWwStrm
);
3098 pTableStrm
= &xTableStrm
;
3099 pDataStrm
= &xDataStrm
;
3101 Strm().SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
3103 utl::TempFile aTempMain
;
3104 aTempMain
.EnableKillingFile();
3105 utl::TempFile aTempTable
;
3106 aTempTable
.EnableKillingFile();
3107 utl::TempFile aTempData
;
3108 aTempData
.EnableKillingFile();
3110 msfilter::MSCodec_Std97 aCtx
;
3111 bool bEncrypt
= m_pWriter
? m_pWriter
->InitStd97CodecUpdateMedium( aCtx
) : false;
3114 GetWriter().SetStream(
3115 aTempMain
.GetStream( STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
) );
3117 pTableStrm
= aTempTable
.GetStream( STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
);
3119 pDataStrm
= aTempData
.GetStream( STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
);
3121 sal_uInt8 aRC4EncryptionHeader
[ 52 ] = {0};
3122 pTableStrm
->Write( aRC4EncryptionHeader
, 52 );
3125 // Default: "Standard"
3126 pSepx
= new WW8_WrPlcSepx( *this ); // Sections/headers/footers
3128 pFtn
= new WW8_WrPlcFtnEdn( TXT_FTN
); // Footnotes
3129 pEdn
= new WW8_WrPlcFtnEdn( TXT_EDN
); // Endnotes
3130 pAtn
= new WW8_WrPlcAnnotations
; // PostIts
3131 pTxtBxs
= new WW8_WrPlcTxtBoxes( TXT_TXTBOX
);
3132 pHFTxtBxs
= new WW8_WrPlcTxtBoxes( TXT_HFTXTBOX
);
3134 pSdrObjs
= new MainTxtPlcDrawObj
; // Draw-/Fly-Objects for main text
3135 pHFSdrObjs
= new HdFtPlcDrawObj
; // Draw-/Fly-Objects for header/footer
3137 pBkmks
= new WW8_WrtBookmarks
; // Bookmarks
3138 GetWriter().CreateBookmarkTbl();
3140 pPapPlc
= new WW8_WrPlcPn( *this, PAP
, pFib
->fcMin
);
3141 pChpPlc
= new WW8_WrPlcPn( *this, CHP
, pFib
->fcMin
);
3142 pO
= new ww::bytes();
3143 pStyles
= new MSWordStyles( *this );
3144 pFldMain
= new WW8_WrPlcFld( 2, TXT_MAINTEXT
);
3145 pFldHdFt
= new WW8_WrPlcFld( 2, TXT_HDFT
);
3146 pFldFtn
= new WW8_WrPlcFld( 2, TXT_FTN
);
3147 pFldEdn
= new WW8_WrPlcFld( 2, TXT_EDN
);
3148 pFldAtn
= new WW8_WrPlcFld( 2, TXT_ATN
);
3149 pFldTxtBxs
= new WW8_WrPlcFld( 2, TXT_TXTBOX
);
3150 pFldHFTxtBxs
= new WW8_WrPlcFld( 2, TXT_HFTXTBOX
);
3152 pMagicTable
= new WW8_WrMagicTable
;
3154 pGrf
= new SwWW8WrGrf( *this );
3155 pPiece
= new WW8_WrPct( pFib
->fcMin
, bWrtWW8
);
3159 pDop
->fRevMarking
= 0 != ( nsRedlineMode_t::REDLINE_ON
& mnRedlineMode
);
3160 pDop
->fRMView
= 0 != ( nsRedlineMode_t::REDLINE_SHOW_DELETE
& mnRedlineMode
);
3161 pDop
->fRMPrint
= pDop
->fRMView
;
3163 // set AutoHyphenation flag if found in default para style
3164 const SfxPoolItem
* pItem
;
3165 SwTxtFmtColl
* pStdTxtFmtColl
=
3166 pDoc
->GetTxtCollFromPool(RES_POOLCOLL_STANDARD
, false);
3167 if (pStdTxtFmtColl
&& SFX_ITEM_SET
== pStdTxtFmtColl
->GetItemState(
3168 RES_PARATR_HYPHENZONE
, false, &pItem
))
3170 pDop
->fAutoHyphen
= ((const SvxHyphenZoneItem
*)pItem
)->IsHyphen();
3177 SvStream
*pStrmTemp
, *pTableStrmTemp
, *pDataStrmTemp
;
3178 pStrmTemp
= &xWwStrm
;
3179 pTableStrmTemp
= &xTableStrm
;
3180 pDataStrmTemp
= &xDataStrm
;
3182 if ( pDataStrmTemp
&& pDataStrmTemp
!= pStrmTemp
)
3183 EncryptRC4(aCtx
, *pDataStrm
, *pDataStrmTemp
);
3185 EncryptRC4(aCtx
, *pTableStrm
, *pTableStrmTemp
);
3187 // Write Unencrypted Header 52 bytes to the start of the table stream
3188 // EncryptionVersionInfo (4 bytes): A Version structure where Version.vMajor MUST be 0x0001, and Version.vMinor MUST be 0x0001.
3189 pTableStrmTemp
->Seek( 0 );
3190 sal_uInt32 nEncType
= 0x10001;
3191 *pTableStrmTemp
<< nEncType
;
3193 sal_uInt8 pDocId
[16];
3194 aCtx
.GetDocId( pDocId
);
3196 sal_uInt8 pSaltData
[16];
3197 sal_uInt8 pSaltDigest
[16];
3198 aCtx
.GetEncryptKey( pDocId
, pSaltData
, pSaltDigest
);
3200 pTableStrmTemp
->Write( pDocId
, 16 );
3201 pTableStrmTemp
->Write( pSaltData
, 16 );
3202 pTableStrmTemp
->Write( pSaltDigest
, 16 );
3204 EncryptRC4(aCtx
, GetWriter().Strm(), *pStrmTemp
);
3206 // Write Unencrypted Fib 68 bytes to the start of the workdocument stream
3207 pFib
->fEncrypted
= 1; // fEncrypted indicates the document is encrypted.
3208 pFib
->fObfuscated
= 0; // Must be 0 for RC4.
3209 pFib
->nHash
= 0x34; // encrypt header bytes count of table stream.
3210 pFib
->nKey
= 0; // lkey2 must be 0 for RC4.
3212 pStrmTemp
->Seek( 0 );
3213 pFib
->WriteHeader( *pStrmTemp
);
3216 if (pUsedNumTbl
) // all used NumRules
3218 // clear the part of the list array that was copied from the document
3219 // - it's an auto delete array, so the rest of the array which are
3220 // duplicated lists that were added during the export will be deleted.
3221 pUsedNumTbl
->erase(pUsedNumTbl
->begin(), pUsedNumTbl
->begin() + pUsedNumTbl
->size() - nUniqueList
);
3226 DELETEZ( pMagicTable
);
3228 DELETEZ( pFldTxtBxs
);
3229 DELETEZ( pFldHFTxtBxs
);
3232 DELETEZ( pFldHdFt
);
3233 DELETEZ( pFldMain
);
3240 delete pRedlAuthors
;
3252 GetWriter().SetStream( 0 );
3255 xWwStrm
->SetBufferSize( 0 );
3258 xTableStrm
->SetBufferSize( 0 );
3259 xDataStrm
->SetBufferSize( 0 );
3260 if( 0 == pDataStrm
->Seek( STREAM_SEEK_TO_END
))
3264 GetWriter().GetStorage().Remove(OUString(SL::aData
));
3270 void WW8Export::PrepareStorage()
3273 const sal_uInt8
* pData
;
3279 static const char aUserName
[] = "Microsoft Word-Document";
3280 static const sal_uInt8 aCompObj
[] =
3282 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3283 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x09, 0x02, 0x00,
3284 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3285 0x00, 0x00, 0x00, 0x46, 0x18, 0x00, 0x00, 0x00,
3286 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
3287 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x2D, 0x44,
3288 0x6F, 0x6B, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x00,
3289 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x53, 0x57, 0x6F,
3290 0x72, 0x64, 0x44, 0x6F, 0x63, 0x00, 0x10, 0x00,
3291 0x00, 0x00, 0x57, 0x6F, 0x72, 0x64, 0x2E, 0x44,
3292 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E,
3293 0x38, 0x00, 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00,
3294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3300 nLen
= sizeof( aCompObj
);
3305 static const char aUserName
[] = "Microsoft Word 6.0 Document";
3306 static const sal_uInt8 aCompObj
[] =
3308 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3309 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x09, 0x02, 0x00,
3310 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3311 0x00, 0x00, 0x00, 0x46, 0x1C, 0x00, 0x00, 0x00,
3312 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
3313 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x20, 0x36,
3314 0x2E, 0x30, 0x2D, 0x44, 0x6F, 0x6B, 0x75, 0x6D,
3315 0x65, 0x6E, 0x74, 0x00, 0x0A, 0x00, 0x00, 0x00,
3316 0x4D, 0x53, 0x57, 0x6F, 0x72, 0x64, 0x44, 0x6F,
3317 0x63, 0x00, 0x10, 0x00, 0x00, 0x00, 0x57, 0x6F,
3318 0x72, 0x64, 0x2E, 0x44, 0x6F, 0x63, 0x75, 0x6D,
3319 0x65, 0x6E, 0x74, 0x2E, 0x36, 0x00, 0x00, 0x00,
3325 nLen
= sizeof( aCompObj
);
3329 SvGlobalName
aGName( nId1
, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00,
3330 0x00, 0x00, 0x00, 0x46 );
3331 GetWriter().GetStorage().SetClass( aGName
, 0, OUString::createFromAscii( pName
));
3332 SvStorageStreamRef
xStor( GetWriter().GetStorage().OpenSotStream(sCompObj
) );
3333 xStor
->Write( pData
, nLen
);
3335 SwDocShell
* pDocShell
= pDoc
->GetDocShell ();
3336 OSL_ENSURE(pDocShell
, "no SwDocShell");
3339 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
3340 pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
3341 uno::Reference
<document::XDocumentProperties
> xDocProps(
3342 xDPS
->getDocumentProperties());
3343 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
3347 if ( SvtFilterOptions::Get().IsEnableWordPreview() )
3349 ::boost::shared_ptr
<GDIMetaFile
> pMetaFile
=
3350 pDocShell
->GetPreviewMetaFile (sal_False
);
3351 uno::Sequence
<sal_uInt8
> metaFile(
3352 sfx2::convertMetaFile(pMetaFile
.get()));
3353 sfx2::SaveOlePropertySet(xDocProps
, &GetWriter().GetStorage(), &metaFile
);
3356 sfx2::SaveOlePropertySet( xDocProps
, &GetWriter().GetStorage() );
3361 sal_uLong
SwWW8Writer::WriteStorage()
3363 // #i34818# - update layout (if present), for SwWriteTable
3364 ViewShell
* pViewShell
= NULL
;
3365 pDoc
->GetEditShell( &pViewShell
);
3366 if( pViewShell
!= NULL
)
3367 pViewShell
->CalcLayout();
3369 long nMaxNode
= pDoc
->GetNodes().Count();
3370 ::StartProgress( STR_STATSTR_W4WWRITE
, 0, nMaxNode
, pDoc
->GetDocShell() );
3372 // Respect table at the beginning of the document
3374 SwTableNode
* pTNd
= pCurPam
->GetNode()->FindTableNode();
3375 if( pTNd
&& bWriteAll
)
3376 // start with the table node !!
3377 pCurPam
->GetPoint()->nNode
= *pTNd
;
3380 // Do the actual export
3382 WW8Export
aExport( this, pDoc
, pCurPam
, pOrigPam
, m_bWrtWW8
);
3383 m_pExport
= &aExport
;
3384 aExport
.ExportDocument( bWriteAll
);
3388 ::EndProgress( pDoc
->GetDocShell() );
3392 sal_uLong
SwWW8Writer::WriteMedium( SfxMedium
& )
3394 return WriteStorage();
3397 sal_uLong
SwWW8Writer::Write( SwPaM
& rPaM
, SfxMedium
& rMed
,
3398 const String
* pFileName
)
3401 sal_uLong nRet
= StgWriter::Write( rPaM
, rMed
, pFileName
);
3406 MSWordExportBase::MSWordExportBase( SwDoc
*pDocument
, SwPaM
*pCurrentPam
, SwPaM
*pOriginalPam
)
3407 : aMainStg(sMainStream
), pISet(0), pUsedNumTbl(0), mpTopNodeOfHdFtPage(0),
3408 pBmpPal(0), pOLEExp(0), pOCXExp(0),
3409 mpTableInfo(new ww8::WW8TableInfo()), nUniqueList(0),
3410 mnHdFtIndex(0), pAktPageDesc(0), pPapPlc(0), pChpPlc(0), pChpIter(0),
3412 bHasHdr(false), bHasFtr(false), bSubstituteBullets(true),
3413 mbExportModeRTF( false ),
3414 mbOutOutlineOnly( false ),
3416 pCurPam( pCurrentPam
),
3417 pOrigPam( pOriginalPam
)
3421 MSWordExportBase::~MSWordExportBase()
3428 WW8Export::WW8Export( SwWW8Writer
*pWriter
,
3429 SwDoc
*pDocument
, SwPaM
*pCurrentPam
, SwPaM
*pOriginalPam
,
3431 : MSWordExportBase( pDocument
, pCurrentPam
, pOriginalPam
),
3435 m_pWriter( pWriter
),
3436 m_pAttrOutput( new WW8AttributeOutput( *this ) )
3440 WW8Export::~WW8Export()
3442 delete m_pAttrOutput
, m_pAttrOutput
= NULL
;
3445 AttributeOutputBase
& WW8Export::AttrOutput() const
3447 return *m_pAttrOutput
;
3450 MSWordSections
& WW8Export::Sections() const
3455 SwWW8Writer::SwWW8Writer(const String
& rFltName
, const String
& rBaseURL
)
3457 m_bWrtWW8( rFltName
.EqualsAscii( FILTER_WW8
) ),
3461 SetBaseURL( rBaseURL
);
3464 SwWW8Writer::~SwWW8Writer()
3468 extern "C" SAL_DLLPUBLIC_EXPORT sal_uLong SAL_CALL
SaveOrDelMSVBAStorage_ww8( SfxObjectShell
& rDoc
, SotStorage
& rStor
, sal_Bool bSaveInto
, const String
& rStorageName
)
3470 SvxImportMSVBasic
aTmp( rDoc
, rStor
);
3471 return aTmp
.SaveOrDelMSVBAStorage( bSaveInto
, rStorageName
);
3474 extern "C" SAL_DLLPUBLIC_EXPORT
void SAL_CALL
ExportDOC( const String
& rFltName
, const String
& rBaseURL
, WriterRef
& xRet
)
3476 xRet
= new SwWW8Writer( rFltName
, rBaseURL
);
3480 extern "C" SAL_DLLPUBLIC_EXPORT sal_uLong SAL_CALL
GetSaveWarningOfMSVBAStorage_ww8( SfxObjectShell
&rDocS
)
3482 return SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( rDocS
);
3485 bool WW8_WrPlcFtnEdn::WriteTxt( WW8Export
& rWrt
)
3488 if (TXT_FTN
== nTyp
)
3490 bRet
= WriteGenericTxt( rWrt
, TXT_FTN
, rWrt
.pFib
->ccpFtn
);
3491 rWrt
.pFldFtn
->Finish( rWrt
.Fc2Cp( rWrt
.Strm().Tell() ),
3492 rWrt
.pFib
->ccpText
);
3496 bRet
= WriteGenericTxt( rWrt
, TXT_EDN
, rWrt
.pFib
->ccpEdn
);
3497 rWrt
.pFldEdn
->Finish( rWrt
.Fc2Cp( rWrt
.Strm().Tell() ),
3498 rWrt
.pFib
->ccpText
+ rWrt
.pFib
->ccpFtn
3499 + rWrt
.pFib
->ccpHdr
+ rWrt
.pFib
->ccpAtn
);
3504 void WW8_WrPlcFtnEdn::WritePlc( WW8Export
& rWrt
) const
3506 if( TXT_FTN
== nTyp
)
3508 WriteGenericPlc( rWrt
, TXT_FTN
, rWrt
.pFib
->fcPlcffndTxt
,
3509 rWrt
.pFib
->lcbPlcffndTxt
, rWrt
.pFib
->fcPlcffndRef
,
3510 rWrt
.pFib
->lcbPlcffndRef
);
3514 WriteGenericPlc( rWrt
, TXT_EDN
, rWrt
.pFib
->fcPlcfendTxt
,
3515 rWrt
.pFib
->lcbPlcfendTxt
, rWrt
.pFib
->fcPlcfendRef
,
3516 rWrt
.pFib
->lcbPlcfendRef
);
3521 bool WW8_WrPlcAnnotations::WriteTxt( WW8Export
& rWrt
)
3523 bool bRet
= WriteGenericTxt( rWrt
, TXT_ATN
, rWrt
.pFib
->ccpAtn
);
3524 rWrt
.pFldAtn
->Finish( rWrt
.Fc2Cp( rWrt
.Strm().Tell() ),
3525 rWrt
.pFib
->ccpText
+ rWrt
.pFib
->ccpFtn
3526 + rWrt
.pFib
->ccpHdr
);
3530 void WW8_WrPlcAnnotations::WritePlc( WW8Export
& rWrt
) const
3532 WriteGenericPlc( rWrt
, TXT_ATN
, rWrt
.pFib
->fcPlcfandTxt
,
3533 rWrt
.pFib
->lcbPlcfandTxt
, rWrt
.pFib
->fcPlcfandRef
,
3534 rWrt
.pFib
->lcbPlcfandRef
);
3537 void WW8_WrPlcTxtBoxes::WritePlc( WW8Export
& rWrt
) const
3539 if( TXT_TXTBOX
== nTyp
)
3541 WriteGenericPlc( rWrt
, nTyp
, rWrt
.pFib
->fcPlcftxbxBkd
,
3542 rWrt
.pFib
->lcbPlcftxbxBkd
, rWrt
.pFib
->fcPlcftxbxTxt
,
3543 rWrt
.pFib
->lcbPlcftxbxTxt
);
3547 WriteGenericPlc( rWrt
, nTyp
, rWrt
.pFib
->fcPlcfHdrtxbxBkd
,
3548 rWrt
.pFib
->lcbPlcfHdrtxbxBkd
, rWrt
.pFib
->fcPlcfHdrtxbxTxt
,
3549 rWrt
.pFib
->lcbPlcfHdrtxbxTxt
);
3553 void WW8Export::RestoreMacroCmds()
3555 pFib
->fcCmds
= pTableStrm
->Tell();
3557 uno::Reference
< embed::XStorage
> xSrcRoot(pDoc
->GetDocShell()->GetStorage());
3560 uno::Reference
< io::XStream
> xSrcStream
=
3561 xSrcRoot
->openStreamElement( OUString(SL::aMSMacroCmds
), embed::ElementModes::READ
);
3562 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( xSrcStream
);
3564 if ( pStream
&& SVSTREAM_OK
== pStream
->GetError())
3566 pStream
->Seek(STREAM_SEEK_TO_END
);
3567 pFib
->lcbCmds
= pStream
->Tell();
3570 sal_uInt8
*pBuffer
= new sal_uInt8
[pFib
->lcbCmds
];
3571 bool bReadOk
= checkRead(*pStream
, pBuffer
, pFib
->lcbCmds
);
3573 pTableStrm
->Write(pBuffer
, pFib
->lcbCmds
);
3580 catch ( const uno::Exception
& )
3585 pFib
->lcbCmds
= pTableStrm
->Tell() - pFib
->fcCmds
;
3588 void WW8SHDLong::Write( WW8Export
& rExport
)
3590 rExport
.InsUInt32( m_cvFore
);
3591 rExport
.InsUInt32( m_cvBack
);
3592 rExport
.InsUInt16( m_ipat
);
3595 void WW8Export::WriteFormData( const ::sw::mark::IFieldmark
& rFieldmark
)
3597 OSL_ENSURE( bWrtWW8
, "No 95 export yet" );
3601 const ::sw::mark::IFieldmark
* pFieldmark
= &rFieldmark
;
3602 const ::sw::mark::ICheckboxFieldmark
* pAsCheckbox
= dynamic_cast< const ::sw::mark::ICheckboxFieldmark
* >( pFieldmark
);
3605 OSL_ENSURE(rFieldmark
.GetFieldname() == ODF_FORMTEXT
||
3606 rFieldmark
.GetFieldname() == ODF_FORMDROPDOWN
||
3607 rFieldmark
.GetFieldname() == ODF_FORMCHECKBOX
, "Unknown field type!!!");
3608 if ( ! ( rFieldmark
.GetFieldname() == ODF_FORMTEXT
||
3609 rFieldmark
.GetFieldname() == ODF_FORMDROPDOWN
||
3610 rFieldmark
.GetFieldname() == ODF_FORMCHECKBOX
) )
3613 int type
= 0; // TextFieldmark
3616 if ( rFieldmark
.GetFieldname() == ODF_FORMDROPDOWN
)
3619 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pNameParameter
= rFieldmark
.GetParameters()->find("name");
3621 if(pNameParameter
!= rFieldmark
.GetParameters()->end())
3622 pNameParameter
->second
>>= ffname
;
3624 sal_uLong nDataStt
= pDataStrm
->Tell();
3625 pChpPlc
->AppendFkpEntry(Strm().Tell());
3628 static sal_uInt8 aArr1
[] =
3630 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
3632 0x06, 0x08, 0x01, // sprmCFData
3633 0x55, 0x08, 0x01, // sprmCFSpec
3634 0x02, 0x08, 0x01 // sprmCFFldVanish
3636 sal_uInt8
* pDataAdr
= aArr1
+ 2;
3637 Set_UInt32(pDataAdr
, nDataStt
);
3639 pChpPlc
->AppendFkpEntry( Strm().Tell(), sizeof( aArr1
), aArr1
);
3647 FFDataHeader() : version( 0xFFFFFFFF ), bits(0), cch(0), hps(0) {}
3651 FFDataHeader aFldHeader
;
3652 aFldHeader
.bits
|= (type
& 0x03);
3654 sal_Int32 ffres
= 0; // rFieldmark.GetFFRes();
3655 if ( pAsCheckbox
&& pAsCheckbox
->IsChecked() )
3657 else if ( type
== 2 )
3659 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pResParameter
= rFieldmark
.GetParameters()->find(ODF_FORMDROPDOWN_RESULT
);
3660 if(pResParameter
!= rFieldmark
.GetParameters()->end())
3661 pResParameter
->second
>>= ffres
;
3665 aFldHeader
.bits
|= ( (ffres
<<2) & 0x7C );
3667 std::vector
< OUString
> aListItems
;
3670 aFldHeader
.bits
|= 0x8000; // ffhaslistbox
3671 const ::sw::mark::IFieldmark::parameter_map_t
* const pParameters
= rFieldmark
.GetParameters();
3672 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries
= pParameters
->find(ODF_FORMDROPDOWN_LISTENTRY
);
3673 if(pListEntries
!= pParameters
->end())
3675 uno::Sequence
< OUString
> vListEntries
;
3676 pListEntries
->second
>>= vListEntries
;
3677 copy(::comphelper::stl_begin(vListEntries
), ::comphelper::stl_end(vListEntries
), back_inserter(aListItems
));
3681 const OUString ffdeftext
;
3682 const OUString ffformat
;
3683 const OUString ffhelptext
;
3684 const OUString ffstattext
;
3685 const OUString ffentrymcr
;
3686 const OUString ffexitmcr
;
3689 const sal_uInt8 aFldData
[] =
3691 0x44,0, // the start of "next" data
3692 0,0,0,0,0,0,0,0,0,0, // PIC-Structure! /10
3693 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3694 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3695 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
3698 sal_uInt32 slen
= sizeof(sal_uInt32
)
3700 + sizeof( aFldHeader
.version
) + sizeof( aFldHeader
.bits
) + sizeof( aFldHeader
.cch
) + sizeof( aFldHeader
.hps
)
3701 + 2*ffname
.getLength() + 4
3702 + 2*ffformat
.getLength() + 4
3703 + 2*ffhelptext
.getLength() + 4
3704 + 2*ffstattext
.getLength() + 4
3705 + 2*ffentrymcr
.getLength() + 4
3706 + 2*ffexitmcr
.getLength() + 4;
3710 slen
+= 2*ffdeftext
.getLength() + 4; //xstzTextDef
3712 slen
+= 2; // sttb ( fExtend )
3713 slen
+= 4; // for num of list items
3714 const int items
= aListItems
.size();
3715 for( int i
= 0; i
< items
; i
++ ) {
3716 OUString item
= aListItems
[i
];
3717 slen
+= 2 * item
.getLength() + 2;
3723 int len
= sizeof( aFldData
);
3724 OSL_ENSURE( len
== 0x44-sizeof(sal_uInt32
), "SwWW8Writer::WriteFormData(..) - wrong aFldData length" );
3725 pDataStrm
->Write( aFldData
, len
);
3727 *pDataStrm
<< aFldHeader
.version
<< aFldHeader
.bits
<< aFldHeader
.cch
<< aFldHeader
.hps
;
3729 SwWW8Writer::WriteString_xstz( *pDataStrm
, ffname
, true ); // Form field name
3732 SwWW8Writer::WriteString_xstz( *pDataStrm
, ffdeftext
, true );
3734 *pDataStrm
<< sal_uInt16(0);
3737 SwWW8Writer::WriteString_xstz( *pDataStrm
, String( ffformat
), true );
3738 SwWW8Writer::WriteString_xstz( *pDataStrm
, String( ffhelptext
), true );
3739 SwWW8Writer::WriteString_xstz( *pDataStrm
, String( ffstattext
), true );
3740 SwWW8Writer::WriteString_xstz( *pDataStrm
, String( ffentrymcr
), true );
3741 SwWW8Writer::WriteString_xstz( *pDataStrm
, String( ffexitmcr
), true );
3743 *pDataStrm
<<(sal_uInt16
)0xFFFF;
3744 const int items
=aListItems
.size();
3745 *pDataStrm
<<(sal_uInt32
)items
;
3746 for(int i
=0;i
<items
;i
++) {
3747 OUString item
=aListItems
[i
];
3748 SwWW8Writer::WriteString_xstz( *pDataStrm
, item
, false );
3753 void WW8Export::WriteHyperlinkData( const sw::mark::IFieldmark
& /*rFieldmark*/ )
3755 //@TODO implement me !!!
3758 void WW8AttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner
)
3761 ShortToSVBT16( m_rWW8Export
.nStyleBeforeFly
, nStyle
);
3764 SAL_INFO( "sw.ww8", "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner
->toString());
3767 m_rWW8Export
.pO
->clear();
3769 sal_uInt32 nShadowsBefore
= pNodeInfoInner
->getShadowsBefore();
3770 if (nShadowsBefore
> 0)
3772 ww8::WW8TableNodeInfoInner::Pointer_t
3773 pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL
));
3775 pTmpNodeInfoInner
->setDepth(pNodeInfoInner
->getDepth());
3776 pTmpNodeInfoInner
->setEndOfCell(true);
3778 for (sal_uInt32 n
= 0; n
< nShadowsBefore
; ++n
)
3780 m_rWW8Export
.WriteCR(pTmpNodeInfoInner
);
3782 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), (sal_uInt8
*)&nStyle
, (sal_uInt8
*)&nStyle
+2 ); // Style #
3783 TableInfoCell(pTmpNodeInfoInner
);
3784 m_rWW8Export
.pPapPlc
->AppendFkpEntry
3785 ( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
3787 m_rWW8Export
.pO
->clear();
3791 if (pNodeInfoInner
->isEndOfCell())
3793 SAL_INFO( "sw.ww8", "<endOfCell/>" );
3795 m_rWW8Export
.WriteCR(pNodeInfoInner
);
3797 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), (sal_uInt8
*)&nStyle
, (sal_uInt8
*)&nStyle
+2 ); // Style #
3798 TableInfoCell(pNodeInfoInner
);
3799 m_rWW8Export
.pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
3801 m_rWW8Export
.pO
->clear();
3804 sal_uInt32 nShadowsAfter
= pNodeInfoInner
->getShadowsAfter();
3805 if (nShadowsAfter
> 0)
3807 ww8::WW8TableNodeInfoInner::Pointer_t
3808 pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL
));
3810 pTmpNodeInfoInner
->setDepth(pNodeInfoInner
->getDepth());
3811 pTmpNodeInfoInner
->setEndOfCell(true);
3813 for (sal_uInt32 n
= 0; n
< nShadowsAfter
; ++n
)
3815 m_rWW8Export
.WriteCR(pTmpNodeInfoInner
);
3817 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), (sal_uInt8
*)&nStyle
, (sal_uInt8
*)&nStyle
+2 ); // Style #
3818 TableInfoCell(pTmpNodeInfoInner
);
3819 m_rWW8Export
.pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
3821 m_rWW8Export
.pO
->clear();
3825 if (pNodeInfoInner
->isEndOfLine())
3827 SAL_INFO( "sw.ww8", "<endOfLine/>" );
3829 TableRowEnd(pNodeInfoInner
->getDepth());
3831 ShortToSVBT16(0, nStyle
);
3832 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), (sal_uInt8
*)&nStyle
, (sal_uInt8
*)&nStyle
+2 ); // Style #
3833 TableInfoRow(pNodeInfoInner
);
3834 m_rWW8Export
.pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
3836 m_rWW8Export
.pO
->clear();
3838 SAL_INFO( "sw.ww8", "</OutWW8_TableNodeInfoInner>" );
3841 void MSWordExportBase::OutputStartNode( const SwStartNode
& rNode
)
3844 ww8::WW8TableNodeInfo::Pointer_t pNodeInfo
=
3845 mpTableInfo
->getTableNodeInfo( &rNode
);
3847 if (pNodeInfo
.get() != NULL
)
3850 SAL_INFO( "sw.ww8", pNodeInfo
->toString());
3852 const ww8::WW8TableNodeInfo::Inners_t aInners
= pNodeInfo
->getInners();
3853 ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator
aIt(aInners
.rbegin());
3854 ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator
aEnd(aInners
.rend());
3857 ww8::WW8TableNodeInfoInner::Pointer_t pInner
= aIt
->second
;
3859 AttrOutput().TableNodeInfoInner(pInner
);
3863 SAL_INFO( "sw.ww8", "</OutWW8_SwStartNode>" );
3866 void MSWordExportBase::OutputEndNode( const SwEndNode
&rNode
)
3869 SAL_INFO( "sw.ww8", "<OutWW8_SwEndNode>" << dbg_out(&rNode
));
3872 ww8::WW8TableNodeInfo::Pointer_t pNodeInfo
= mpTableInfo
->getTableNodeInfo( &rNode
);
3874 if (pNodeInfo
.get() != NULL
)
3877 SAL_INFO( "sw.ww8", pNodeInfo
->toString());
3880 const ww8::WW8TableNodeInfo::Inners_t aInners
= pNodeInfo
->getInners();
3881 ww8::WW8TableNodeInfo::Inners_t::const_iterator
aIt(aInners
.begin());
3882 ww8::WW8TableNodeInfo::Inners_t::const_iterator
aEnd(aInners
.end());
3885 ww8::WW8TableNodeInfoInner::Pointer_t pInner
= aIt
->second
;
3886 AttrOutput().TableNodeInfoInner(pInner
);
3890 SAL_INFO( "sw.ww8", "</OutWW8_SwEndNode>" );
3893 const NfKeywordTable
& MSWordExportBase::GetNfKeywordTable()
3895 if (pKeyMap
.get() == NULL
)
3897 pKeyMap
.reset(new NfKeywordTable
);
3898 NfKeywordTable
& rKeywordTable
= *pKeyMap
;
3899 rKeywordTable
[NF_KEY_D
] = "d";
3900 rKeywordTable
[NF_KEY_DD
] = "dd";
3901 rKeywordTable
[NF_KEY_DDD
] = "ddd";
3902 rKeywordTable
[NF_KEY_DDDD
] = "dddd";
3903 rKeywordTable
[NF_KEY_M
] = "M";
3904 rKeywordTable
[NF_KEY_MM
] = "MM";
3905 rKeywordTable
[NF_KEY_MMM
] = "MMM";
3906 rKeywordTable
[NF_KEY_MMMM
] = "MMMM";
3907 rKeywordTable
[NF_KEY_NN
] = "ddd";
3908 rKeywordTable
[NF_KEY_NNN
] = "dddd";
3909 rKeywordTable
[NF_KEY_NNNN
] = "dddd";
3910 rKeywordTable
[NF_KEY_YY
] = "yy";
3911 rKeywordTable
[NF_KEY_YYYY
] = "yyyy";
3912 rKeywordTable
[NF_KEY_H
] = "H";
3913 rKeywordTable
[NF_KEY_HH
] = "HH";
3914 rKeywordTable
[NF_KEY_MI
] = "m";
3915 rKeywordTable
[NF_KEY_MMI
] = "mm";
3916 rKeywordTable
[NF_KEY_S
] = "s";
3917 rKeywordTable
[NF_KEY_SS
] = "ss";
3918 rKeywordTable
[NF_KEY_AMPM
] = "AM/PM";
3924 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */