Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx
Warning:line 1424, column 35
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name wrtww8.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include <iostream>
22
23#include <com/sun/star/embed/ElementModes.hpp>
24#include <com/sun/star/embed/XStorage.hpp>
25#include <com/sun/star/frame/XModel.hpp>
26#include <com/sun/star/packages/XPackageEncryption.hpp>
27#include <com/sun/star/uno/XComponentContext.hpp>
28#include <unotools/ucbstreamhelper.hxx>
29#include <unotools/streamwrap.hxx>
30#include <algorithm>
31#include <map>
32#include <hintids.hxx>
33#include <string.h>
34#include <o3tl/safeint.hxx>
35#include <osl/endian.h>
36#include <sal/log.hxx>
37#include <docsh.hxx>
38#include <drawdoc.hxx>
39
40#include <unotools/fltrcfg.hxx>
41#include <sot/storage.hxx>
42#include <sfx2/docinf.hxx>
43#include <editeng/tstpitem.hxx>
44#include <svx/svdpage.hxx>
45#include <editeng/hyphenzoneitem.hxx>
46#include <filter/msfilter/classids.hxx>
47#include <filter/msfilter/msoleexp.hxx>
48#include <editeng/lrspitem.hxx>
49#include <editeng/ulspitem.hxx>
50#include <editeng/boxitem.hxx>
51#include <editeng/brushitem.hxx>
52#include <swtypes.hxx>
53#include <swrect.hxx>
54#include <swtblfmt.hxx>
55#include <fmtcntnt.hxx>
56#include <fmtpdsc.hxx>
57#include <fmtrowsplt.hxx>
58#include <frmatr.hxx>
59#include <../../core/inc/rootfrm.hxx>
60#include <doc.hxx>
61#include <IDocumentSettingAccess.hxx>
62#include <IDocumentDrawModelAccess.hxx>
63#include <IDocumentStylePoolAccess.hxx>
64#include <IDocumentStatistics.hxx>
65#include <IDocumentLayoutAccess.hxx>
66#include <IDocumentExternalData.hxx>
67#include <viewopt.hxx>
68#include <docary.hxx>
69#include <pam.hxx>
70#include <ndtxt.hxx>
71#include <shellio.hxx>
72#include <docstat.hxx>
73#include <pagedesc.hxx>
74#include <poolfmt.hxx>
75#include <IMark.hxx>
76#include <swtable.hxx>
77#include "wrtww8.hxx"
78#include "ww8par.hxx"
79#include <swmodule.hxx>
80#include <section.hxx>
81#include <fmtinfmt.hxx>
82#include <txtinet.hxx>
83#include <fmturl.hxx>
84#include <vcl/imap.hxx>
85#include <vcl/imapobj.hxx>
86#include <mdiexp.hxx>
87#include <strings.hrc>
88#include <fmtline.hxx>
89#include <fmtfsize.hxx>
90#include "sprmids.hxx"
91
92#include <comphelper/sequenceashashmap.hxx>
93#include <comphelper/processfactory.hxx>
94#include "writerhelper.hxx"
95#include "writerwordglue.hxx"
96#include "ww8attributeoutput.hxx"
97#include <xmloff/odffields.hxx>
98#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
99#include <com/sun/star/document/XDocumentProperties.hpp>
100#include <dbgoutsw.hxx>
101#include <sfx2/docfile.hxx>
102#include <sfx2/frame.hxx>
103#include <svl/stritem.hxx>
104#include <unotools/tempfile.hxx>
105#include <filter/msfilter/mscodec.hxx>
106#include <filter/msfilter/svxmsbas.hxx>
107#include <rtl/random.h>
108#include <vcl/svapp.hxx>
109#include <sfx2/docfilt.hxx>
110#include "WW8Sttbf.hxx"
111#include <editeng/charrotateitem.hxx>
112#include <svx/swframetypes.hxx>
113#include "WW8FibData.hxx"
114#include <numrule.hxx>
115#include <fmtclds.hxx>
116#include <rdfhelper.hxx>
117#include <fmtclbl.hxx>
118#include <iodetect.hxx>
119
120using namespace css;
121using namespace sw::util;
122using namespace sw::types;
123
124/** FKP - Formatted disK Page
125*/
126class WW8_WrFkp
127{
128 sal_uInt8* pFkp; // Fkp total ( first and only FCs and Sprms )
129 sal_uInt8* pOfs; // pointer to the offset area, later copied to pFkp
130 ePLCFT ePlc;
131 short nStartGrp; // from here on grpprls
132 short nOldStartGrp;
133 sal_uInt8 nItemSize;
134 sal_uInt8 nIMax; // number of entry pairs
135 sal_uInt8 nOldVarLen;
136 bool bCombined; // true : paste not allowed
137
138 sal_uInt8 SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms );
139
140 WW8_WrFkp(const WW8_WrFkp&) = delete;
141 WW8_WrFkp& operator=(const WW8_WrFkp&) = delete;
142
143public:
144 WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc);
145 ~WW8_WrFkp();
146 bool Append( WW8_FC nEndFc, sal_uInt16 nVarLen, const sal_uInt8* pSprms );
147 void Combine();
148 void Write( SvStream& rStrm, SwWW8WrGrf& rGrf );
149
150 bool IsEqualPos(WW8_FC nEndFc) const
151 { return !bCombined && nIMax && nEndFc == reinterpret_cast<sal_Int32*>(pFkp)[nIMax]; }
152 void MergeToNew( short& rVarLen, sal_uInt8 *& pNewSprms );
153 bool IsEmptySprm() const
154 { return !bCombined && nIMax && !nOldVarLen; }
155 void SetNewEnd( WW8_FC nEnd )
156 { reinterpret_cast<sal_Int32*>(pFkp)[nIMax] = nEnd; }
157
158 WW8_FC GetStartFc() const;
159 WW8_FC GetEndFc() const;
160
161 sal_uInt8 *CopyLastSprms(sal_uInt8 &rLen);
162};
163
164// class WW8_WrPc collects all piece entries for one piece
165class WW8_WrPc
166{
167 WW8_CP nStartCp; // Starting character position of the text
168 WW8_FC nStartFc; // Starting file position of the text
169 sal_uInt16 nStatus; // End of paragraph inside the piece?
170
171public:
172 WW8_WrPc(WW8_FC nSFc, WW8_CP nSCp )
173 : nStartCp( nSCp ), nStartFc( nSFc ), nStatus( 0x0040 )
174 {}
175
176 void SetStatus() { nStatus = 0x0050; }
177 sal_uInt16 GetStatus() const { return nStatus; }
178 WW8_CP GetStartCp() const { return nStartCp; }
179 WW8_FC GetStartFc() const { return nStartFc; }
180};
181
182typedef std::map<OUString,long> BKMKNames;
183typedef std::pair<bool,OUString> BKMK;
184typedef std::pair<long,BKMK> BKMKCP;
185typedef std::multimap<long,BKMKCP*> BKMKCPs;
186typedef BKMKCPs::iterator CPItr;
187
188class WW8_WrtBookmarks
189{
190private:
191 /// Structure of one item inside this map: (startPos, (endPos, (a bool value?, bookmarkName)))
192 BKMKCPs aSttCps;
193 BKMKNames maSwBkmkNms;
194
195 WW8_WrtBookmarks(WW8_WrtBookmarks const&) = delete;
196 WW8_WrtBookmarks& operator=(WW8_WrtBookmarks const&) = delete;
197
198public:
199 WW8_WrtBookmarks();
200 ~WW8_WrtBookmarks();
201 //! Add a new bookmark to the list OR add an end position to an existing bookmark.
202 void Append( WW8_CP nStartCp, const OUString& rNm );
203 //! Write out bookmarks to file.
204 void Write( WW8Export& rWrt );
205 //! Move existing field marks from one position to another.
206 void MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo);
207};
208
209WW8_WrtBookmarks::WW8_WrtBookmarks()
210{}
211
212WW8_WrtBookmarks::~WW8_WrtBookmarks()
213{
214 for (auto& rEntry : aSttCps)
215 {
216 if (rEntry.second)
217 {
218 delete rEntry.second;
219 rEntry.second = nullptr;
220 }
221 }
222}
223
224void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const OUString& rNm)
225{
226 std::pair<BKMKNames::iterator, bool> aResult = maSwBkmkNms.insert(std::pair<OUString,long>(rNm,0L));
227 if (aResult.second)
228 {
229 BKMK aBK(false,rNm);
230 BKMKCP* pBKCP = new BKMKCP(static_cast<long>(nStartCp),aBK);
231 aSttCps.insert(std::pair<long,BKMKCP*>(nStartCp,pBKCP));
232 aResult.first->second = static_cast<long>(nStartCp);
233 }
234 else
235 {
236 std::pair<CPItr,CPItr> aRange = aSttCps.equal_range(aResult.first->second);
237 for (CPItr aItr = aRange.first;aItr != aRange.second;++aItr)
238 {
239 if (aItr->second && aItr->second->second.second == rNm)
240 {
241 if (aItr->second->second.first)
242 nStartCp--;
243 aItr->second->first = static_cast<long>(nStartCp);
244 break;
245 }
246 }
247 }
248}
249
250void WW8_WrtBookmarks::Write( WW8Export& rWrt)
251{
252 if (aSttCps.empty())
253 return;
254 long n;
255 std::vector<OUString> aNames;
256 SvMemoryStream aTempStrm1(65535,65535);
257 SvMemoryStream aTempStrm2(65535,65535);
258
259 BKMKCPs aEndCps;
260 for (const auto& rEntry : aSttCps)
261 {
262 if (rEntry.second)
263 {
264 aEndCps.insert(std::pair<long,BKMKCP*>(rEntry.second->first, rEntry.second));
265 aNames.push_back(rEntry.second->second.second);
266 SwWW8Writer::WriteLong(aTempStrm1, rEntry.first);
267 }
268 }
269
270 aTempStrm1.Seek(0);
271 n = 0;
272 for (const auto& rEntry : aEndCps)
273 {
274 if (rEntry.second)
275 {
276 rEntry.second->first = n;
277 SwWW8Writer::WriteLong( aTempStrm2, rEntry.first);
278 }
279 ++n;
280 }
281
282 aTempStrm2.Seek(0);
283 rWrt.WriteAsStringTable(aNames, rWrt.pFib->m_fcSttbfbkmk,rWrt.pFib->m_lcbSttbfbkmk);
284 SvStream& rStrm = *rWrt.pTableStrm;
285 rWrt.pFib->m_fcPlcfbkf = rStrm.Tell();
286 rStrm.WriteStream( aTempStrm1 );
287 SwWW8Writer::WriteLong(rStrm, rWrt.pFib->m_ccpText + rWrt.pFib->m_ccpTxbx);
288 for (const auto& rEntry : aSttCps)
289 {
290 if (rEntry.second)
291 {
292 SwWW8Writer::WriteLong(rStrm, rEntry.second->first);
293 }
294 }
295 rWrt.pFib->m_lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->m_fcPlcfbkf;
296 rWrt.pFib->m_fcPlcfbkl = rStrm.Tell();
297 rStrm.WriteStream( aTempStrm2 );
298 SwWW8Writer::WriteLong(rStrm, rWrt.pFib->m_ccpText + rWrt.pFib->m_ccpTxbx);
299 rWrt.pFib->m_lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->m_fcPlcfbkl;
300}
301
302void WW8_WrtBookmarks::MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo)
303{
304 std::pair<CPItr,CPItr> aRange = aSttCps.equal_range(nFrom);
305 CPItr aItr = aRange.first;
306 while (aItr != aRange.second)
307 {
308 if (aItr->second)
309 {
310 if (aItr->second->first == static_cast<long>(nFrom))
311 {
312 aItr->second->second.first = true;
313 aItr->second->first = nTo;
314 }
315 aSttCps.insert(std::pair<long,BKMKCP*>(nTo,aItr->second));
316 aItr->second = nullptr;
317 aRange = aSttCps.equal_range(nFrom);
318 aItr = aRange.first;
319 continue;
320 }
321 ++aItr;
322 }
323}
324
325/// Handles export of smart tags.
326class WW8_WrtFactoids
327{
328 std::vector<WW8_CP> m_aStartCPs;
329 std::vector<WW8_CP> m_aEndCPs;
330 std::vector< std::map<OUString, OUString> > m_aStatements;
331
332 WW8_WrtFactoids(WW8_WrtFactoids const&) = delete;
333 WW8_WrtFactoids& operator=(WW8_WrtFactoids const&) = delete;
334
335public:
336 WW8_WrtFactoids();
337 void Append(WW8_CP nStartCp, WW8_CP nEndCp, const std::map<OUString, OUString>& rStatements);
338 void Write(WW8Export& rWrt);
339};
340
341WW8_WrtFactoids::WW8_WrtFactoids()
342{
343}
344
345void WW8_WrtFactoids::Append(WW8_CP nStartCp, WW8_CP nEndCp, const std::map<OUString, OUString>& rStatements)
346{
347 m_aStartCPs.push_back(nStartCp);
348 m_aEndCPs.push_back(nEndCp);
349 m_aStatements.push_back(rStatements);
350}
351
352void WW8_WrtFactoids::Write(WW8Export& rExport)
353{
354 if (m_aStartCPs.empty())
355 return;
356
357 // Smart tags are otherwise removed by Word on saving.
358 rExport.pDop->fEmbedFactoids = true;
359
360 SvStream& rStream = *rExport.pTableStrm;
361
362 rExport.pFib->m_fcSttbfBkmkFactoid = rStream.Tell();
363 // Write SttbfBkmkFactoid.
364 rStream.WriteUInt16(0xffff); // fExtend
365 rStream.WriteUInt16(m_aStartCPs.size()); // cData
366 rStream.WriteUInt16(0); // cbExtra
367
368 for (size_t i = 0; i < m_aStartCPs.size(); ++i)
369 {
370 rStream.WriteUInt16(6); // cchData
371 // Write FACTOIDINFO.
372 rStream.WriteUInt32(i); // dwId
373 rStream.WriteUInt16(0); // fSubEntry
374 rStream.WriteUInt16(0); // fto
375 rStream.WriteUInt32(0); // pfpb
376 }
377 rExport.pFib->m_lcbSttbfBkmkFactoid = rStream.Tell() - rExport.pFib->m_fcSttbfBkmkFactoid;
378
379 rExport.pFib->m_fcPlcfBkfFactoid = rStream.Tell();
380 for (const WW8_CP& rCP : m_aStartCPs)
381 rStream.WriteInt32(rCP);
382 rStream.WriteInt32(rExport.pFib->m_ccpText + rExport.pFib->m_ccpTxbx);
383
384 // Write FBKFD.
385 for (size_t i = 0; i < m_aStartCPs.size(); ++i)
386 {
387 rStream.WriteInt16(i); // ibkl
388 rStream.WriteInt16(0); // bkc
389 rStream.WriteInt16(1); // cDepth, 1 as start and end is the same.
390 }
391
392 rExport.pFib->m_lcbPlcfBkfFactoid = rStream.Tell() - rExport.pFib->m_fcPlcfBkfFactoid;
393
394 rExport.pFib->m_fcPlcfBklFactoid = rStream.Tell();
395 for (const WW8_CP& rCP : m_aEndCPs)
396 rStream.WriteInt32(rCP);
397 rStream.WriteInt32(rExport.pFib->m_ccpText + rExport.pFib->m_ccpTxbx);
398
399 // Write FBKLD.
400 for (size_t i = 0; i < m_aEndCPs.size(); ++i)
401 {
402 rStream.WriteInt16(i); // ibkf
403 rStream.WriteInt16(0); // cDepth, 0 as does not overlap with any other smart tag.
404 }
405 rExport.pFib->m_lcbPlcfBklFactoid = rStream.Tell() - rExport.pFib->m_fcPlcfBklFactoid;
406
407 rExport.pFib->m_fcFactoidData = rStream.Tell();
408 // Write SmartTagData.
409 MSOFactoidType aFactoidType;
410 aFactoidType.m_nId = 1;
411 aFactoidType.m_aUri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
412 aFactoidType.m_aTag = "RDF";
413 WW8SmartTagData aSmartTagData;
414 aSmartTagData.m_aPropBagStore.m_aFactoidTypes.push_back(aFactoidType);
415
416 std::set<OUString> aSet;
417 for (const std::map<OUString, OUString>& rStatements : m_aStatements)
418 {
419 // Statements for a single text node.
420 for (const auto& rPair : rStatements)
421 {
422 aSet.insert(rPair.first);
423 aSet.insert(rPair.second);
424 }
425 }
426 aSmartTagData.m_aPropBagStore.m_aStringTable.assign(aSet.begin(), aSet.end());
427 for (const std::map<OUString, OUString>& rStatements : m_aStatements)
428 {
429 MSOPropertyBag aPropertyBag;
430 aPropertyBag.m_nId = 1;
431 for (const auto& rPair : rStatements)
432 {
433 MSOProperty aProperty;
434 aProperty.m_nKey = std::distance(aSet.begin(), aSet.find(rPair.first));
435 aProperty.m_nValue = std::distance(aSet.begin(), aSet.find(rPair.second));
436 aPropertyBag.m_aProperties.push_back(aProperty);
437 }
438 aSmartTagData.m_aPropBags.push_back(aPropertyBag);
439 }
440
441 aSmartTagData.Write(rExport);
442 rExport.pFib->m_lcbFactoidData = rStream.Tell() - rExport.pFib->m_fcFactoidData;
443}
444
445#define DEFAULT_STYLES_COUNT16 16
446
447// Names of the storage streams
448#define sMainStreamOUString("WordDocument") OUString("WordDocument")
449#define sCompObj"\1CompObj" "\1CompObj"
450
451static void WriteDop( WW8Export& rWrt )
452{
453 WW8Dop& rDop = *rWrt.pDop;
454
455 // i#78951#, store the value of unknown compatibility options
456 rDop.SetCompatibilityOptions( rWrt.m_rDoc.getIDocumentSettingAccess().Getn32DummyCompatibilityOptions1());
457 rDop.SetCompatibilityOptions2( rWrt.m_rDoc.getIDocumentSettingAccess().Getn32DummyCompatibilityOptions2());
458
459 rDop.fNoLeading = !rWrt.m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::ADD_EXT_LEADING);
460 rDop.fUsePrinterMetrics = !rWrt.m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::USE_VIRTUAL_DEVICE);
461
462 // write default TabStop
463 const SvxTabStopItem& rTabStop =
464 DefaultItemGet<SvxTabStopItem>(rWrt.m_rDoc, RES_PARATR_TABSTOP);
465 rDop.dxaTab = static_cast<sal_uInt16>(rTabStop[0].GetTabPos());
466
467 // Zoom factor and type
468 SwViewShell *pViewShell(rWrt.m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell());
469 if (pViewShell)
470 {
471 switch ( pViewShell->GetViewOptions()->GetZoomType() )
472 {
473 case SvxZoomType::WHOLEPAGE: rDop.zkSaved = 1; break;
474 case SvxZoomType::PAGEWIDTH: rDop.zkSaved = 2; break;
475 case SvxZoomType::OPTIMAL: rDop.zkSaved = 3; break;
476 default: rDop.zkSaved = 0;
477 rDop.wScaleSaved = pViewShell->GetViewOptions()->GetZoom();
478 break;
479 }
480 }
481
482 // Values from the DocumentStatistics (are definitely needed
483 // for the DocStat fields)
484 rDop.fWCFootnoteEdn = true; // because they are included in StarWriter
485
486 const SwDocStat& rDStat = rWrt.m_rDoc.getIDocumentStatistics().GetDocStat();
487 rDop.cWords = rDStat.nWord;
488 rDop.cCh = rDStat.nChar;
489 rDop.cPg = static_cast< sal_Int16 >(rDStat.nPage);
490 rDop.cParas = rDStat.nPara;
491 rDop.cLines = rDStat.nPara;
492
493 SwDocShell *pDocShell(rWrt.m_rDoc.GetDocShell());
494 OSL_ENSURE(pDocShell, "no SwDocShell")do { if (true && (!(pDocShell))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "494" ": "), "%s", "no SwDocShell"); } } while (false)
;
495 uno::Reference<document::XDocumentProperties> xDocProps;
496 uno::Reference<beans::XPropertySet> xProps;
497 if ( pDocShell )
498 {
499 xProps.set(pDocShell->GetModel(), uno::UNO_QUERY);
500
501 rDop.lKeyProtDoc = pDocShell->GetModifyPasswordHash();
502 }
503
504 if ((rWrt.pSepx && rWrt.pSepx->DocumentIsProtected()) ||
505 rWrt.m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_FORM ) ||
506 rDop.lKeyProtDoc != 0)
507 {
508 rDop.fProtEnabled = true;
509 // The password was ignored at import if forms protection was enabled,
510 // so round-trip it since protection is still enabled.
511 if ( rDop.lKeyProtDoc == 0 && xProps.is() )
512 {
513 comphelper::SequenceAsHashMap aPropMap( xProps->getPropertyValue("InteropGrabBag"));
514 aPropMap.getValue("FormPasswordHash") >>= rDop.lKeyProtDoc;
515 }
516 }
517 else
518 {
519 rDop.fProtEnabled = false;
520 }
521
522 if (!xDocProps.is())
523 {
524 rDop.dttmCreated = rDop.dttmRevised = rDop.dttmLastPrint = 0x45FBAC69;
525 }
526 else
527 {
528 ::util::DateTime uDT = xDocProps->getCreationDate();
529 rDop.dttmCreated = sw::ms::DateTime2DTTM(DateTime(uDT));
530 uDT = xDocProps->getModificationDate();
531 rDop.dttmRevised = sw::ms::DateTime2DTTM(DateTime(uDT));
532 uDT = xDocProps->getPrintDate();
533 rDop.dttmLastPrint = sw::ms::DateTime2DTTM(DateTime(uDT));
534 }
535
536 // Also, the DocStat fields in headers, footers are not calculated correctly.
537 // ( we do not have this fields! )
538
539 // and also for the Headers and Footers
540 rDop.cWordsFootnoteEnd = rDStat.nWord;
541 rDop.cChFootnoteEdn = rDStat.nChar;
542 rDop.cPgFootnoteEdn = static_cast<sal_Int16>(rDStat.nPage);
543 rDop.cParasFootnoteEdn = rDStat.nPara;
544 rDop.cLinesFootnoteEdn = rDStat.nPara;
545
546 rDop.fDontUseHTMLAutoSpacing = rWrt.m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::PARA_SPACE_MAX);
547
548 rDop.fExpShRtn = !rWrt.m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK); // #i56856#
549
550 rDop.Write( *rWrt.pTableStrm, *rWrt.pFib );
551}
552
553static int lcl_CmpBeginEndChars( const OUString& rSWStr,
554 const sal_Unicode* pMSStr, int nMSStrByteLen )
555{
556 nMSStrByteLen /= sizeof( sal_Unicode );
557 if( nMSStrByteLen > rSWStr.getLength() )
558 nMSStrByteLen = rSWStr.getLength()+1;
559 nMSStrByteLen *= sizeof( sal_Unicode );
560
561 return memcmp( rSWStr.getStr(), pMSStr, nMSStrByteLen );
562}
563
564/*
565Converts the OOo Asian Typography into a best fit match for Microsoft
566Asian typography. This structure is actually dumped to disk within the
567Dop Writer. Assumption is that rTypo is cleared to 0 on entry
568*/
569void WW8Export::ExportDopTypography(WW8DopTypography &rTypo)
570{
571 static const sal_Unicode aLangNotBegin[4][WW8DopTypography::nMaxFollowing]=
572 {
573 //Japanese Level 1
574 {
575 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
576 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
577 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
578 0x300f, 0x3011, 0x3015, 0x3041, 0x3043, 0x3045, 0x3047, 0x3049,
579 0x3063, 0x3083, 0x3085, 0x3087, 0x308e, 0x309b, 0x309c, 0x309d,
580 0x309e, 0x30a1, 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30c3, 0x30e3,
581 0x30e5, 0x30e7, 0x30ee, 0x30f5, 0x30f6, 0x30fb, 0x30fc, 0x30fd,
582 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b,
583 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65, 0xff67,
584 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
585 0xff70, 0xff9e, 0xff9f, 0xffe0
586 },
587 //Simplified Chinese
588 {
589 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
590 0x007d, 0x00a8, 0x00b7, 0x02c7, 0x02c9, 0x2015, 0x2016, 0x2019,
591 0x201d, 0x2026, 0x2236, 0x3001, 0x3002, 0x3003, 0x3005, 0x3009,
592 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x3017, 0xff01, 0xff02,
593 0xff07, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
594 0xff40, 0xff5c, 0xff5d, 0xff5e, 0xffe0
595 },
596 //Korean
597 {
598 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
599 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2032, 0x2033,
600 0x2103, 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0xff01,
601 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
602 0xff5d, 0xffe0
603 },
604 //Traditional Chinese
605 {
606 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
607 0x007d, 0x00a2, 0x00b7, 0x2013, 0x2014, 0x2019, 0x201d, 0x2022,
608 0x2025, 0x2026, 0x2027, 0x2032, 0x2574, 0x3001, 0x3002, 0x3009,
609 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x301e, 0xfe30, 0xfe31,
610 0xfe33, 0xfe34, 0xfe36, 0xfe38, 0xfe3a, 0xfe3c, 0xfe3e, 0xfe40,
611 0xfe42, 0xfe44, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55,
612 0xfe56, 0xfe57, 0xfe5a, 0xfe5c, 0xfe5e, 0xff01, 0xff09, 0xff0c,
613 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff5c, 0xff5d, 0xff64
614 },
615 };
616
617 static const sal_Unicode aLangNotEnd[4][WW8DopTypography::nMaxLeading] =
618 {
619 //Japanese Level 1
620 {
621 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
622 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
623 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
624 },
625 //Simplified Chinese
626 {
627 0x0028, 0x005b, 0x007b, 0x00b7, 0x2018, 0x201c, 0x3008, 0x300a,
628 0x300c, 0x300e, 0x3010, 0x3014, 0x3016, 0xff08, 0xff0e, 0xff3b,
629 0xff5b, 0xffe1, 0xffe5
630 },
631 //Korean
632 {
633 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c,
634 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04, 0xff08,
635 0xff3b, 0xff5b, 0xffe6
636 },
637 //Traditional Chinese
638 {
639 0x0028, 0x005b, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c, 0x2035,
640 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0x301d, 0xfe35,
641 0xfe37, 0xfe39, 0xfe3b, 0xfe3d, 0xfe3f, 0xfe41, 0xfe43, 0xfe59,
642 0xfe5b, 0xfe5d, 0xff08, 0xff5b
643 },
644 };
645
646 const i18n::ForbiddenCharacters *pForbidden = nullptr;
647 const i18n::ForbiddenCharacters *pUseMe = nullptr;
648 sal_uInt8 nUseReserved=0;
649 int nNoNeeded=0;
650 /*
651 Now we have some minor difficult issues, to wit...
652 a. MicroSoft Office can only store one set of begin and end characters in
653 a given document, not one per language.
654 b. StarOffice has only a concept of one set of begin and end characters for
655 a given language, i.e. not the two levels of kinsoku in japanese
656
657 What is unknown as yet is if our default begin and end chars for
658 japanese, chinese tradition, chinese simplified and korean are different
659 in Word and Writer. I already suspect that they are different between
660 different version of word itself.
661
662 So what have come up with is to simply see if any of the four languages
663 in OOo have been changed away from OUR defaults, and if one has then
664 export that. If more than one has in the future we may hack in something
665 which examines our document properties to see which language is used the
666 most and choose that, for now we choose the first and throw an ASSERT
667 */
668
669 /*Our default Japanese Level is 2, this is a special MS hack to set this*/
670 rTypo.m_reserved2 = 1;
671
672 for (rTypo.m_reserved1=8;rTypo.m_reserved1>0;rTypo.m_reserved1-=2)
673 {
674 pForbidden = m_rDoc.getIDocumentSettingAccess().getForbiddenCharacters(rTypo.GetConvertedLang(),
675 false);
676 if (nullptr != pForbidden)
677 {
678 int nIdx = (rTypo.m_reserved1-2)/2;
679 if( lcl_CmpBeginEndChars( pForbidden->endLine,
680 aLangNotEnd[ nIdx ], sizeof(aLangNotEnd[ nIdx ]) ) ||
681 lcl_CmpBeginEndChars( pForbidden->beginLine,
682 aLangNotBegin[ nIdx ], sizeof(aLangNotBegin[ nIdx ]) ) )
683 {
684 //One exception for Japanese, if it matches a level 1 we
685 //can use one extra flag for that, rather than use a custom
686 if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESELanguageType(0x0411))
687 {
688 if (
689 !lcl_CmpBeginEndChars
690 (
691 pForbidden->endLine,
692 WW8DopTypography::JapanNotEndLevel1,
693 WW8DopTypography::nMaxLeading * sizeof(sal_Unicode)
694 )
695 &&
696 !lcl_CmpBeginEndChars
697 (
698 pForbidden->beginLine,
699 WW8DopTypography::JapanNotBeginLevel1,
700 WW8DopTypography::nMaxFollowing * sizeof(sal_Unicode)
701 )
702 )
703 {
704 rTypo.m_reserved2 = 0;
705 continue;
706 }
707 }
708
709 if (!pUseMe)
710 {
711 pUseMe = pForbidden;
712 nUseReserved = rTypo.m_reserved1;
713 rTypo.m_iLevelOfKinsoku = 2;
714 }
715 nNoNeeded++;
716 }
717 }
718 }
719
720 OSL_ENSURE( nNoNeeded<=1, "Example of unexportable forbidden chars" )do { if (true && (!(nNoNeeded<=1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "720" ": "), "%s", "Example of unexportable forbidden chars"
); } } while (false)
;
721 rTypo.m_reserved1=nUseReserved;
722 if (rTypo.m_iLevelOfKinsoku && pUseMe)
723 {
724 rTypo.m_cchFollowingPunct = msword_cast<sal_Int16>
725 (pUseMe->beginLine.getLength());
726 if (rTypo.m_cchFollowingPunct > WW8DopTypography::nMaxFollowing - 1)
727 rTypo.m_cchFollowingPunct = WW8DopTypography::nMaxFollowing - 1;
728
729 rTypo.m_cchLeadingPunct = msword_cast<sal_Int16>
730 (pUseMe->endLine.getLength());
731 if (rTypo.m_cchLeadingPunct > WW8DopTypography::nMaxLeading - 1)
732 rTypo.m_cchLeadingPunct = WW8DopTypography::nMaxLeading -1;
733
734 memcpy(rTypo.m_rgxchFPunct,pUseMe->beginLine.getStr(),
735 (rTypo.m_cchFollowingPunct+1)*2);
736
737 memcpy(rTypo.m_rgxchLPunct,pUseMe->endLine.getStr(),
738 (rTypo.m_cchLeadingPunct+1)*2);
739 }
740
741 const IDocumentSettingAccess& rIDocumentSettingAccess = GetWriter().getIDocumentSettingAccess();
742
743 rTypo.m_fKerningPunct = sal_uInt16(rIDocumentSettingAccess.get(DocumentSettingId::KERN_ASIAN_PUNCTUATION));
744 rTypo.m_iJustification = sal_uInt16(m_rDoc.getIDocumentSettingAccess().getCharacterCompressionType());
745}
746
747// It can only be found something with this method, if it is used within
748// WW8_SwAttrIter::OutAttr() and WW8Export::OutputItemSet()
749const SfxPoolItem* MSWordExportBase::HasItem( sal_uInt16 nWhich ) const
750{
751 const SfxPoolItem* pItem=nullptr;
752 if (m_pISet)
753 {
754 // if write an EditEngine text, then the WhichIds are greater than
755 // our own Ids. So the Id have to translate from our into the
756 // EditEngine Range
757 nWhich = sw::hack::GetSetWhichFromSwDocWhich(*m_pISet, m_rDoc, nWhich);
758 if (nWhich && SfxItemState::SET != m_pISet->GetItemState(nWhich, true, &pItem))
759 pItem = nullptr;
760 }
761 else if( m_pChpIter )
762 pItem = m_pChpIter->HasTextItem( nWhich );
763 else
764 {
765 OSL_ENSURE( false, "Where is my ItemSet / pChpIter ?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "765" ": "), "%s", "Where is my ItemSet / pChpIter ?"); }
} while (false)
;
766 pItem = nullptr;
767 }
768 return pItem;
769}
770
771const SfxPoolItem& MSWordExportBase::GetItem(sal_uInt16 nWhich) const
772{
773 assert((m_pISet || m_pChpIter) && "Where is my ItemSet / pChpIter ?")(static_cast <bool> ((m_pISet || m_pChpIter) &&
"Where is my ItemSet / pChpIter ?") ? void (0) : __assert_fail
("(m_pISet || m_pChpIter) && \"Where is my ItemSet / pChpIter ?\""
, "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
, 773, __extension__ __PRETTY_FUNCTION__))
;
774 if (m_pISet)
775 {
776 // if write an EditEngine text, then the WhichIds are greater than
777 // our own Ids. So the Id have to translate from our into the
778 // EditEngine Range
779 nWhich = sw::hack::GetSetWhichFromSwDocWhich(*m_pISet, m_rDoc, nWhich);
780 OSL_ENSURE(nWhich != 0, "All broken, Impossible")do { if (true && (!(nWhich != 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "780" ": "), "%s", "All broken, Impossible"); } } while (
false)
;
781 return m_pISet->Get(nWhich);
782 }
783 return m_pChpIter->GetItem( nWhich );
784}
785
786WW8_WrPlc1::WW8_WrPlc1( sal_uInt16 nStructSz )
787 : pData( new sal_uInt8[ 16 * nStructSz ] ),
788 nDataLen(16 * nStructSz),
789 nStructSiz( nStructSz )
790{
791}
792
793WW8_WrPlc1::~WW8_WrPlc1()
794{
795}
796
797WW8_CP WW8_WrPlc1::Prev() const
798{
799 bool b = !aPos.empty();
800 OSL_ENSURE(b,"Prev called on empty list")do { if (true && (!(b))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "800" ": "), "%s", "Prev called on empty list"); } } while
(false)
;
801 return b ? aPos.back() : 0;
802}
803
804void WW8_WrPlc1::Append( WW8_CP nCp, const void* pNewData )
805{
806 sal_uLong nInsPos = aPos.size() * nStructSiz;
807 aPos.push_back( nCp );
808 if( nDataLen < nInsPos + nStructSiz )
809 {
810 sal_uInt8* pNew = new sal_uInt8[ 2 * nDataLen ];
811 memcpy( pNew, pData.get(), nDataLen );
812 pData.reset(pNew);
813 nDataLen *= 2;
814 }
815 memcpy( pData.get() + nInsPos, pNewData, nStructSiz );
816}
817
818void WW8_WrPlc1::Finish( sal_uLong nLastCp, sal_uLong nSttCp )
819{
820 if( !aPos.empty() )
821 {
822 aPos.push_back( nLastCp );
823 if( nSttCp )
824 for(WW8_CP & rCp : aPos)
825 rCp -= nSttCp;
826 }
827}
828
829void WW8_WrPlc1::Write( SvStream& rStrm )
830{
831 decltype(aPos)::size_type i;
832 for( i = 0; i < aPos.size(); ++i )
833 SwWW8Writer::WriteLong( rStrm, aPos[i] );
834 if( i )
835 rStrm.WriteBytes(pData.get(), (i-1) * nStructSiz);
836}
837
838// Class WW8_WrPlcField for fields
839
840void WW8_WrPlcField::Write( WW8Export& rWrt )
841{
842 if( WW8_WrPlc1::Count() <= 1 )
843 return;
844
845 WW8_FC *pfc;
846 sal_Int32 *plc;
847 switch (nTextTyp)
848 {
849 case TXT_MAINTEXT:
850 pfc = &rWrt.pFib->m_fcPlcffldMom;
851 plc = &rWrt.pFib->m_lcbPlcffldMom;
852 break;
853 case TXT_HDFT:
854 pfc = &rWrt.pFib->m_fcPlcffldHdr;
855 plc = &rWrt.pFib->m_lcbPlcffldHdr;
856 break;
857
858 case TXT_FTN:
859 pfc = &rWrt.pFib->m_fcPlcffldFootnote;
860 plc = &rWrt.pFib->m_lcbPlcffldFootnote;
861 break;
862
863 case TXT_EDN:
864 pfc = &rWrt.pFib->m_fcPlcffldEdn;
865 plc = &rWrt.pFib->m_lcbPlcffldEdn;
866 break;
867
868 case TXT_ATN:
869 pfc = &rWrt.pFib->m_fcPlcffldAtn;
870 plc = &rWrt.pFib->m_lcbPlcffldAtn;
871 break;
872
873 case TXT_TXTBOX:
874 pfc = &rWrt.pFib->m_fcPlcffldTxbx;
875 plc = &rWrt.pFib->m_lcbPlcffldTxbx;
876 break;
877
878 case TXT_HFTXTBOX:
879 pfc = &rWrt.pFib->m_fcPlcffldHdrTxbx;
880 plc = &rWrt.pFib->m_lcbPlcffldHdrTxbx;
881 break;
882
883 default:
884 pfc = plc = nullptr;
885 break;
886 }
887
888 if( pfc && plc )
889 {
890 sal_uInt64 nFcStart = rWrt.pTableStrm->Tell();
891 WW8_WrPlc1::Write( *rWrt.pTableStrm );
892 *pfc = nFcStart;
893 *plc = rWrt.pTableStrm->Tell() - nFcStart;
894 }
895}
896
897void WW8_WrMagicTable::Write( WW8Export& rWrt )
898{
899 if( WW8_WrPlc1::Count() <= 1 )
900 return;
901 sal_uLong nFcStart = rWrt.pTableStrm->Tell();
902 WW8_WrPlc1::Write( *rWrt.pTableStrm );
903 rWrt.pFib->m_fcPlcfTch = nFcStart;
904 rWrt.pFib->m_lcbPlcfTch = rWrt.pTableStrm->Tell() - nFcStart;
905}
906
907void WW8_WrMagicTable::Append( WW8_CP nCp, sal_uLong nData)
908{
909 /*
910 Tell the undocumented table hack that everything between here and the last
911 table position is non-table text, don't do it if the previous position is
912 the same as this one, as that would be a region of 0 length
913 */
914 if ((!Count()) || (Prev() != nCp))
915 {
916 SVBT32 nLittle;
917 UInt32ToSVBT32(nData,nLittle);
918 WW8_WrPlc1::Append(nCp, nLittle);
919 }
920}
921
922void SwWW8Writer::FillCount( SvStream& rStrm, sal_uLong nCount )
923{
924 static const sal_uInt32 aNulls[16] =
925 {
926 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 64 Byte
927 };
928
929 while (nCount > 64)
930 {
931 rStrm.WriteBytes(aNulls, 64); // in steps of 64-Byte
932 nCount -= 64;
933 }
934 rStrm.WriteBytes(aNulls, nCount); // write the rest (0 .. 64 Bytes)
935}
936
937sal_uLong SwWW8Writer::FillUntil( SvStream& rStrm, sal_uLong nEndPos )
938{
939 sal_uInt64 nCurPos = rStrm.Tell();
940 if( !nEndPos ) // nEndPos == 0 -> next Page
941 nEndPos = (nCurPos + 0x1ff) & ~0x1ffUL;
942
943 if( nEndPos > nCurPos )
944 SwWW8Writer::FillCount( rStrm, nEndPos - nCurPos );
945#if OSL_DEBUG_LEVEL1 > 0
946 else
947 OSL_ENSURE( nEndPos == nCurPos, "Wrong FillUntil()" )do { if (true && (!(nEndPos == nCurPos))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "947" ": "), "%s", "Wrong FillUntil()"); } } while (false
)
;
948#endif
949 return rStrm.Tell();
950}
951
952WW8_WrPlcPn::WW8_WrPlcPn(WW8Export& rWr, ePLCFT ePl, WW8_FC nStartFc)
953 : rWrt(rWr)
954 , nFkpStartPage(0)
955 , ePlc(ePl)
956{
957 m_Fkps.push_back(std::make_unique<WW8_WrFkp>(ePlc, nStartFc));
958}
959
960WW8_WrPlcPn::~WW8_WrPlcPn()
961{
962}
963
964sal_uInt8 *WW8_WrPlcPn::CopyLastSprms(sal_uInt8 &rLen)
965{
966 WW8_WrFkp& rF = *m_Fkps.back();
967 return rF.CopyLastSprms(rLen);
968}
969
970void WW8_WrPlcPn::AppendFkpEntry(WW8_FC nEndFc,short nVarLen,const sal_uInt8* pSprms)
971{
972 WW8_WrFkp* pF = m_Fkps.back().get();
973
974 // big sprm? build the sprmPHugePapx
975 sal_uInt8* pNewSprms = const_cast<sal_uInt8*>(pSprms);
976 sal_uInt8 aHugePapx[ 8 ];
977 if (PAP == ePlc && 488 <= nVarLen)
978 {
979 sal_uInt8* p = aHugePapx;
980 *p++ = *pSprms++; // set style Id
981 *p++ = *pSprms++;
982 nVarLen -= 2;
983
984 long nDataPos = rWrt.pDataStrm->Tell();
985 SwWW8Writer::WriteShort( *rWrt.pDataStrm, nVarLen );
986 rWrt.pDataStrm->WriteBytes(pSprms, nVarLen);
987
988 Set_UInt16( p, 0x6646 ); // set SprmCode
989 Set_UInt32( p, nDataPos ); // set startpos (FC) in the datastream
990 nVarLen = static_cast< short >(p - aHugePapx);
991 pSprms = pNewSprms = aHugePapx;
992 }
993 // if append at the same FC-EndPos and there are sprms, then get the old
994 // sprms and erase it; they will append now with the new sprms
995 else if( nVarLen && pF->IsEqualPos( nEndFc ))
996 pF->MergeToNew( nVarLen, pNewSprms );
997 // has the prev EndFC an empty sprm and the current is empty too, then
998 // expand only the old EndFc to the new EndFc
999 else if( !nVarLen && pF->IsEmptySprm() )
1000 {
1001 pF->SetNewEnd( nEndFc );
1002 return ;
1003 }
1004
1005 bool bOk = pF->Append(nEndFc, nVarLen, pNewSprms);
1006 if( !bOk )
1007 {
1008 pF->Combine();
1009 pF = new WW8_WrFkp(ePlc, pF->GetEndFc()); // Start new Fkp == end of old Fkp
1010
1011 m_Fkps.push_back(std::unique_ptr<WW8_WrFkp>(pF));
1012 if( !pF->Append( nEndFc, nVarLen, pNewSprms ) )
1013 {
1014 OSL_ENSURE( false, "Unable to insert Sprm" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1014" ": "), "%s", "Unable to insert Sprm"); } } while (
false)
;
1015 }
1016 }
1017 if( pNewSprms != pSprms ) //Merge to new has created a new block
1018 delete[] pNewSprms;
1019}
1020
1021void WW8_WrPlcPn::WriteFkps()
1022{
1023 nFkpStartPage = static_cast<sal_uInt16>( SwWW8Writer::FillUntil( rWrt.Strm() ) >> 9 );
1024
1025 for(const std::unique_ptr<WW8_WrFkp> & rp : m_Fkps)
1026 {
1027 rp->Write( rWrt.Strm(), *rWrt.m_pGrf );
1028 }
1029
1030 if( CHP == ePlc )
1031 {
1032 rWrt.pFib->m_pnChpFirst = nFkpStartPage;
1033 rWrt.pFib->m_cpnBteChp = m_Fkps.size();
1034 }
1035 else
1036 {
1037 rWrt.pFib->m_pnPapFirst = nFkpStartPage;
1038 rWrt.pFib->m_cpnBtePap = m_Fkps.size();
1039 }
1040}
1041
1042void WW8_WrPlcPn::WritePlc()
1043{
1044 sal_uInt64 nFcStart = rWrt.pTableStrm->Tell();
1045 decltype(m_Fkps)::size_type i;
1046
1047 for (i = 0; i < m_Fkps.size(); ++i)
1048 {
1049 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
1050 m_Fkps[ i ]->GetStartFc() );
1051 }
1052
1053 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
1054 m_Fkps[ i - 1 ]->GetEndFc() );
1055
1056 // for every FKP output the page
1057 for (i = 0; i < m_Fkps.size(); ++i)
1058 {
1059 SwWW8Writer::WriteLong( *rWrt.pTableStrm, i + nFkpStartPage );
1060 }
1061
1062 if( CHP == ePlc )
1063 {
1064 rWrt.pFib->m_fcPlcfbteChpx = nFcStart;
1065 rWrt.pFib->m_lcbPlcfbteChpx = rWrt.pTableStrm->Tell() - nFcStart;
1066 }
1067 else
1068 {
1069 rWrt.pFib->m_fcPlcfbtePapx = nFcStart;
1070 rWrt.pFib->m_lcbPlcfbtePapx = rWrt.pTableStrm->Tell() - nFcStart;
1071 }
1072}
1073
1074WW8_WrFkp::WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc)
1075 : ePlc(ePl), nStartGrp(511), nOldStartGrp(511),
1076 nItemSize( ( CHP == ePl ) ? 1 : 13 ),
1077 nIMax(0), nOldVarLen(0), bCombined(false)
1078{
1079 pFkp = reinterpret_cast<sal_uInt8*>(new sal_Int32[128]); // 512 Byte
1080 pOfs = reinterpret_cast<sal_uInt8*>(new sal_Int32[128]); // 512 Byte
1081 memset( pFkp, 0, 4 * 128 );
1082 memset( pOfs, 0, 4 * 128 );
1083 reinterpret_cast<sal_Int32*>(pFkp)[0] = nStartFc; // 0th entry FC at nStartFc
1084}
1085
1086WW8_WrFkp::~WW8_WrFkp()
1087{
1088 delete[] reinterpret_cast<sal_Int32 *>(pFkp);
1089 delete[] reinterpret_cast<sal_Int32 *>(pOfs);
1090}
1091
1092sal_uInt8 WW8_WrFkp::SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms )
1093{
1094 if( 3 < nVarLen )
1095 {
1096 // if the sprms contained picture-references then never equal!
1097 for( sal_uInt8 n = static_cast< sal_uInt8 >(nVarLen - 1); 3 < n; --n )
1098 if( pSprms[ n ] == GRF_MAGIC_30x56 &&
1099 pSprms[ n-1 ] == GRF_MAGIC_20x34 &&
1100 pSprms[ n-2 ] == GRF_MAGIC_10x12 )
1101 return 0;
1102 }
1103
1104 short i;
1105 for( i = 0; i < nIMax; i++ )
1106 {
1107 sal_uInt8 nStart = pOfs[i * nItemSize];
1108 if( nStart )
1109 { // has Sprms
1110 const sal_uInt8* p = pFkp + ( static_cast<sal_uInt16>(nStart) << 1 );
1111 if( ( CHP == ePlc
1112 ? (*p++ == nVarLen)
1113 : ((static_cast<sal_uInt16>(*p++) << 1 ) == (( nVarLen+1) & 0xfffe)) )
1114 && !memcmp( p, pSprms, nVarLen ) )
1115 return nStart; // found it
1116 }
1117 }
1118 return 0; // didn't found it
1119}
1120
1121sal_uInt8 *WW8_WrFkp::CopyLastSprms(sal_uInt8 &rLen)
1122{
1123 rLen=0;
1124 sal_uInt8 *pStart=nullptr,*pRet=nullptr;
1125
1126 if (!bCombined)
1127 pStart = pOfs;
1128 else
1129 pStart = pFkp + ( nIMax + 1 ) * 4;
1130
1131 sal_uInt8 nStart = *(pStart + (nIMax-1) * nItemSize);
1132
1133 const sal_uInt8* p = pFkp + ( static_cast<sal_uInt16>(nStart) << 1 );
1134
1135 if (!*p)
1136 p++;
1137
1138 if (*p)
1139 {
1140 rLen = *p++;
1141 if (PAP == ePlc)
1142 rLen *= 2;
1143 pRet = new sal_uInt8[rLen];
1144 memcpy(pRet,p,rLen);
1145 }
1146 return pRet;
1147}
1148
1149bool WW8_WrFkp::Append( WW8_FC nEndFc, sal_uInt16 nVarLen, const sal_uInt8* pSprms )
1150{
1151 assert((!nVarLen || pSprms) && "Item pointer missing")(static_cast <bool> ((!nVarLen || pSprms) && "Item pointer missing"
) ? void (0) : __assert_fail ("(!nVarLen || pSprms) && \"Item pointer missing\""
, "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
, 1151, __extension__ __PRETTY_FUNCTION__))
;
1152
1153 OSL_ENSURE( nVarLen < ( ( ePlc == PAP ) ? 497U : 502U ), "Sprms too long !" )do { if (true && (!(nVarLen < ( ( ePlc == PAP ) ? 497U
: 502U )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1153" ": "), "%s", "Sprms too long !"); } } while (false
)
;
1154
1155 if( bCombined )
1156 {
1157 OSL_ENSURE( false, "Fkp::Append: Fkp is already combined" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1157" ": "), "%s", "Fkp::Append: Fkp is already combined"
); } } while (false)
;
1158 return false;
1159 }
1160 sal_Int32 n = reinterpret_cast<sal_Int32*>(pFkp)[nIMax]; // last entry
1161 if( nEndFc <= n )
1162 {
1163 OSL_ENSURE( nEndFc >= n, "+Fkp: FC backwards" )do { if (true && (!(nEndFc >= n))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1163" ": "), "%s", "+Fkp: FC backwards"); } } while (false
)
;
1164 OSL_ENSURE( !nVarLen || !pSprms || nEndFc != n,do { if (true && (!(!nVarLen || !pSprms || nEndFc != n
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1165" ": "), "%s", "+Fkp: used same FC multiple times")
; } } while (false)
1165 "+Fkp: used same FC multiple times" )do { if (true && (!(!nVarLen || !pSprms || nEndFc != n
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1165" ": "), "%s", "+Fkp: used same FC multiple times")
; } } while (false)
;
1166 // same FC without Sprm is ignored without grumbling
1167
1168 return true; // ignore (do not create a new Fkp)
1169 }
1170
1171 sal_uInt8 nOldP = nVarLen ? SearchSameSprm( nVarLen, pSprms ) : 0;
1172 // Combine equal entries
1173 short nOffset=0, nPos = nStartGrp;
1174 if (nVarLen && !nOldP)
1175 {
1176 nPos = PAP == ePlc
1177 ? ( 13 == nItemSize // HACK: PAP and bWrtWW8 !!
1178 ? (nStartGrp & 0xFFFE ) - nVarLen - 1
1179 : (nStartGrp - (((nVarLen + 1) & 0xFFFE)+1)) & 0xFFFE )
1180 : ((nStartGrp - nVarLen - 1) & 0xFFFE);
1181 if( nPos < 0 )
1182 return false; // doesn't fit at all
1183 nOffset = nPos; // save offset (can also be uneven!)
1184 nPos &= 0xFFFE; // Pos for Sprms ( gerade Pos )
1185 }
1186
1187 if( o3tl::make_unsigned(nPos) <= ( nIMax + 2U ) * 4U + ( nIMax + 1U ) * nItemSize )
1188 // does it fits after the CPs and offsets?
1189 return false; // no
1190
1191 reinterpret_cast<sal_Int32*>(pFkp)[nIMax + 1] = nEndFc; // insert FC
1192
1193 nOldVarLen = static_cast<sal_uInt8>(nVarLen);
1194 if( nVarLen && !nOldP )
1195 { // insert it for real
1196 nOldStartGrp = nStartGrp;
1197
1198 nStartGrp = nPos;
1199 pOfs[nIMax * nItemSize] = static_cast<sal_uInt8>( nStartGrp >> 1 );
1200 // insert (start-of-data >> 1)
1201 sal_uInt8 nCnt = static_cast< sal_uInt8 >(CHP == ePlc
1202 ? ( nVarLen < 256 ) ? static_cast<sal_uInt8>(nVarLen) : 255
1203 : ( ( nVarLen + 1 ) >> 1 ));
1204
1205 pFkp[ nOffset ] = nCnt; // Enter data length
1206 memcpy( pFkp + nOffset + 1, pSprms, nVarLen ); // store Sprms
1207 }
1208 else
1209 {
1210 // do not enter for real ( no Sprms or recurrence )
1211 // start-of-data 0 ( no data ) or recurrence
1212 pOfs[nIMax * nItemSize] = nOldP;
1213 }
1214 nIMax++;
1215 return true;
1216}
1217
1218void WW8_WrFkp::Combine()
1219{
1220 if( bCombined )
1221 return;
1222 if( nIMax )
1223 memcpy( pFkp + ( nIMax + 1 ) * 4, pOfs, nIMax * nItemSize );
1224 delete[] pOfs;
1225 pOfs = nullptr;
1226 pFkp[511] = nIMax;
1227 bCombined = true;
1228
1229#if defined OSL_BIGENDIAN // only the FCs will be rotated here
1230 sal_uInt16 i; // the Sprms must be rotated elsewhere
1231
1232 sal_uInt32* p;
1233 for( i = 0, p = (sal_uInt32*)pFkp; i <= nIMax; i++, p++ )
1234 *p = OSL_SWAPDWORD( *p )((sal_uInt32)((((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16
)(((sal_uInt16)(((sal_uInt32)(*p) >> 16) & 0xFFFF))
) >> 8) & 0xFF))) & 0xFF) | (((sal_uInt16)(((sal_uInt8
)((sal_uInt16)(((sal_uInt16)(((sal_uInt32)(*p) >> 16) &
0xFFFF))) & 0xFF))) & 0xFF) << 8)))) & 0xFFFF
) | (((sal_uInt32)(((sal_uInt16)((sal_uInt16)((((sal_uInt8)((
(sal_uInt16)(((sal_uInt16)((sal_uInt32)(*p) & 0xFFFF))) >>
8) & 0xFF))) & 0xFF) | (((sal_uInt16)(((sal_uInt8)((
sal_uInt16)(((sal_uInt16)((sal_uInt32)(*p) & 0xFFFF))) &
0xFF))) & 0xFF) << 8)))) & 0xFFFF) << 16
))
;
1235#endif // ifdef OSL_BIGENDIAN
1236}
1237
1238void WW8_WrFkp::Write( SvStream& rStrm, SwWW8WrGrf& rGrf )
1239{
1240 Combine(); // If not already combined
1241
1242 sal_uInt8* p; // search magic for nPicLocFc
1243 sal_uInt8* pEnd = pFkp + nStartGrp;
1244 for( p = pFkp + 511 - 4; p >= pEnd; p-- )
1245 {
1246 if( *p != GRF_MAGIC_10x12 ) // search for signature 0x12 0x34 0x56 0xXX
1247 continue;
1248 if( *(p+1) != GRF_MAGIC_20x34 )
1249 continue;
1250 if( *(p+2) != GRF_MAGIC_30x56 )
1251 continue;
1252
1253 SVBT32 nPos; // signature found
1254 UInt32ToSVBT32( rGrf.GetFPos(), nPos ); // FilePos the graphics
1255 memcpy( p, nPos, 4 ); // patch FilePos over the signature
1256 }
1257 rStrm.WriteBytes(pFkp, 512);
1258}
1259
1260void WW8_WrFkp::MergeToNew( short& rVarLen, sal_uInt8 *& rpNewSprms )
1261{
1262 sal_uInt8 nStart = pOfs[ (nIMax-1) * nItemSize ];
1263 if( !nStart )
1264 return;
1265
1266// has Sprms
1267 sal_uInt8* p = pFkp + ( static_cast<sal_uInt16>(nStart) << 1 );
1268
1269 // old and new equal? Then copy only one into the new sprms
1270 if( nOldVarLen == rVarLen && !memcmp( p+1, rpNewSprms, nOldVarLen ))
1271 {
1272 sal_uInt8* pNew = new sal_uInt8[ nOldVarLen ];
1273 memcpy( pNew, p+1, nOldVarLen );
1274 rpNewSprms = pNew;
1275 }
1276 else
1277 {
1278 sal_uInt8* pNew = new sal_uInt8[ nOldVarLen + rVarLen ];
1279 memcpy( pNew, p+1, nOldVarLen );
1280 memcpy( pNew + nOldVarLen, rpNewSprms, rVarLen );
1281
1282 rpNewSprms = pNew;
1283 rVarLen = rVarLen + nOldVarLen;
1284 }
1285 --nIMax;
1286 // if this Sprms don't used from others, remove it
1287 bool bFnd = false;
1288 for (sal_uInt16 n = 0; n < nIMax; ++n)
1289 {
1290 if (nStart == pOfs[n * nItemSize])
1291 {
1292 bFnd = true;
1293 break;
1294 }
1295 }
1296 if (!bFnd)
1297 {
1298 nStartGrp = nOldStartGrp;
1299 memset( p, 0, nOldVarLen+1 );
1300 }
1301}
1302
1303WW8_FC WW8_WrFkp::GetStartFc() const
1304{
1305 // when bCombined, then the array beginning with pFkp is already byte-swapped
1306 // to LittleEndian, so to extract the start and end positions they must
1307 // be swapped back.
1308 if( bCombined )
1309 return SVBT32ToUInt32( pFkp ); // 0. Element
1310 return reinterpret_cast<sal_Int32*>(pFkp)[0];
1311}
1312
1313WW8_FC WW8_WrFkp::GetEndFc() const
1314{
1315 if( bCombined )
1316 return SVBT32ToUInt32( &(pFkp[nIMax*4]) ); // nIMax-th SVBT32-Element
1317 return reinterpret_cast<sal_Int32*>(pFkp)[nIMax];
1318}
1319
1320// Method for managing the piece table
1321WW8_WrPct::WW8_WrPct(WW8_FC nfcMin)
1322 : nOldFc(nfcMin)
1323{
1324 AppendPc(nOldFc);
1325}
1326
1327WW8_WrPct::~WW8_WrPct()
1328{
1329}
1330
1331// Fill the piece and create a new one
1332void WW8_WrPct::AppendPc(WW8_FC nStartFc)
1333{
1334 WW8_CP nStartCp = nStartFc - nOldFc; // subtract the beginning of the text
1335 if ( !nStartCp && !m_Pcts.empty())
1336 {
1337 OSL_ENSURE(1 == m_Pcts.size(), "empty Piece!")do { if (true && (!(1 == m_Pcts.size()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1337" ": "), "%s", "empty Piece!"); } } while (false)
;
1338 m_Pcts.pop_back();
1339 }
1340
1341 nOldFc = nStartFc; // remember StartFc as old
1342
1343 nStartCp >>= 1; // for Unicode: number of characters / 2
1344
1345 if (!m_Pcts.empty())
1346 {
1347 nStartCp += m_Pcts.back()->GetStartCp();
1348 }
1349
1350 m_Pcts.push_back(std::make_unique<WW8_WrPc>(nStartFc, nStartCp));
1351}
1352
1353void WW8_WrPct::WritePc( WW8Export& rWrt )
1354{
1355 sal_uInt64 nPctStart;
1356 sal_uLong nOldPos, nEndPos;
1357
1358 nPctStart = rWrt.pTableStrm->Tell(); // Start piece table
1359 rWrt.pTableStrm->WriteChar( char(0x02) ); // Status byte PCT
1360 nOldPos = nPctStart + 1; // remember Position
1361 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); // then the length
1362
1363 for (auto const& it : m_Pcts) // ranges
1364 {
1365 SwWW8Writer::WriteLong( *rWrt.pTableStrm, it->GetStartCp() );
1366 }
1367
1368 // calculate the last Pos
1369 sal_uLong nStartCp = rWrt.pFib->m_fcMac - nOldFc;
1370 nStartCp >>= 1; // For Unicode: number of characters / 2
1371 nStartCp += m_Pcts.back()->GetStartCp();
1372 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nStartCp );
1373
1374 // piece references
1375 for (auto const& it : m_Pcts)
1376 {
1377 SwWW8Writer::WriteShort(*rWrt.pTableStrm, it->GetStatus());
1378 SwWW8Writer::WriteLong(*rWrt.pTableStrm, it->GetStartFc());
1379 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0); // PRM=0
1380 }
1381
1382 // entries in the FIB
1383 rWrt.pFib->m_fcClx = nPctStart;
1384 nEndPos = rWrt.pTableStrm->Tell();
1385 rWrt.pFib->m_lcbClx = nEndPos - nPctStart;
1386
1387 // and register the length as well
1388 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nOldPos,
1389 nEndPos - nPctStart-5 );
1390
1391}
1392
1393void WW8_WrPct::SetParaBreak()
1394{
1395 OSL_ENSURE( !m_Pcts.empty(), "SetParaBreak : m_Pcts.empty()" )do { if (true && (!(!m_Pcts.empty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1395" ": "), "%s", "SetParaBreak : m_Pcts.empty()"); } }
while (false)
;
1396 m_Pcts.back()->SetStatus();
1397}
1398
1399WW8_CP WW8_WrPct::Fc2Cp( sal_uLong nFc ) const
1400{
1401 OSL_ENSURE( nFc >= o3tl::make_unsigned(nOldFc), "FilePos lies in front of last piece" )do { if (true && (!(nFc >= o3tl::make_unsigned(nOldFc
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1401" ": "), "%s", "FilePos lies in front of last piece"
); } } while (false)
;
1402 OSL_ENSURE( ! m_Pcts.empty(), "Fc2Cp no piece available" )do { if (true && (!(! m_Pcts.empty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1402" ": "), "%s", "Fc2Cp no piece available"); } } while
(false)
;
1403
1404 nFc -= nOldFc;
1405 nFc /= 2; // Unicode
1406 return nFc + m_Pcts.back()->GetStartCp();
1407}
1408
1409void WW8Export::AppendBookmarks( const SwTextNode& rNd, sal_Int32 nCurrentPos, sal_Int32 nLen )
1410{
1411 std::vector< const ::sw::mark::IMark* > aArr;
1412 sal_uInt16 nContent;
1413 const sal_Int32 nCurrentEnd = nCurrentPos + nLen;
1414 if( !GetWriter().GetBookmarks( rNd, nCurrentPos, nCurrentEnd, aArr ))
1
Assuming the condition is false
2
Taking false branch
1415 return;
1416
1417 sal_uLong nNd = rNd.GetIndex(), nSttCP = Fc2Cp( Strm().Tell() );
1418 for(const ::sw::mark::IMark* p : aArr)
1419 {
1420 const ::sw::mark::IMark& rBkmk = *p;
3
'rBkmk' initialized here
1421 if(dynamic_cast< const ::sw::mark::IFieldmark *>(&rBkmk))
4
Assuming pointer value is null
5
Taking false branch
1422 continue;
1423
1424 const SwPosition* pPos = &rBkmk.GetMarkPos();
6
Called C++ object pointer is null
1425 const SwPosition* pOPos = nullptr;
1426 if(rBkmk.IsExpanded())
1427 pOPos = &rBkmk.GetOtherMarkPos();
1428 if( pOPos && pOPos->nNode == pPos->nNode &&
1429 pOPos->nContent < pPos->nContent )
1430 {
1431 pPos = pOPos;
1432 pOPos = &rBkmk.GetMarkPos();
1433 }
1434
1435 if( !pOPos || ( nNd == pPos->nNode.GetIndex() &&
1436 ( nContent = pPos->nContent.GetIndex() ) >= nCurrentPos &&
1437 nContent < nCurrentEnd ) )
1438 {
1439 sal_uLong nCp = nSttCP + pPos->nContent.GetIndex() - nCurrentPos;
1440 m_pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()));
1441 }
1442 if( pOPos && nNd == pOPos->nNode.GetIndex() &&
1443 ( nContent = pOPos->nContent.GetIndex() ) >= nCurrentPos &&
1444 nContent < nCurrentEnd )
1445 {
1446 sal_uLong nCp = nSttCP + pOPos->nContent.GetIndex() - nCurrentPos;
1447 m_pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()));
1448 }
1449 }
1450}
1451
1452void WW8Export::AppendAnnotationMarks(const SwWW8AttrIter& rAttrs, sal_Int32 nCurrentPos, sal_Int32 nLen)
1453{
1454 IMarkVector aMarks;
1455 if (GetAnnotationMarks(rAttrs, nCurrentPos, nCurrentPos + nLen, aMarks))
1456 {
1457 for (const sw::mark::IMark* pMark : aMarks)
1458 {
1459 const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
1460 if (nStart == nCurrentPos)
1461 {
1462 m_pAtn->AddRangeStartPosition(pMark->GetName(), Fc2Cp(Strm().Tell()),
1463 !rAttrs.HasFlysAt(nCurrentPos));
1464 }
1465 }
1466 }
1467}
1468
1469void WW8Export::AppendSmartTags(SwTextNode& rTextNode)
1470{
1471 std::map<OUString, OUString> aStatements = SwRDFHelper::getTextNodeStatements("urn:bails", rTextNode);
1472 if (!aStatements.empty())
1473 {
1474 WW8_CP nCP = Fc2Cp(Strm().Tell());
1475 m_pFactoids->Append(nCP, nCP, aStatements);
1476 }
1477}
1478
1479void WW8Export::MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo)
1480{
1481 m_pBkmks->MoveFieldMarks(nFrom, nTo);
1482}
1483
1484void WW8Export::AppendBookmark( const OUString& rName )
1485{
1486 sal_uLong nSttCP = Fc2Cp( Strm().Tell() );
1487 m_pBkmks->Append( nSttCP, rName );
1488}
1489
1490void WW8Export::AppendBookmarkEndWithCorrection( const OUString& rName )
1491{
1492 sal_uLong nEndCP = Fc2Cp( Strm().Tell() );
1493 m_pBkmks->Append( nEndCP - 1, rName );
1494}
1495
1496std::unique_ptr<SvxBrushItem> MSWordExportBase::getBackground()
1497{
1498 const SwFrameFormat &rFormat = m_rDoc.GetPageDesc(0).GetMaster();
1499 std::unique_ptr<SvxBrushItem> aBrush = std::make_unique<SvxBrushItem>(RES_BACKGROUND);
1500 SfxItemState eState = rFormat.GetBackgroundState(aBrush);
1501
1502 if (SfxItemState::SET == eState)
1503 {
1504 // The 'color' is set for the first page style - take it and use it as the background color of the entire DOCX
1505 if (aBrush->GetColor() != COL_AUTO)
1506 return aBrush;
1507 }
1508 return nullptr;
1509}
1510
1511// #i120928 collect all the graphics of bullets applied to paragraphs
1512int MSWordExportBase::CollectGrfsOfBullets()
1513{
1514 m_vecBulletPic.clear();
1515
1516 size_t nCountRule = m_rDoc.GetNumRuleTable().size();
1517 for (size_t n = 0; n < nCountRule; ++n)
1518 {
1519 const SwNumRule &rRule = *( m_rDoc.GetNumRuleTable().at(n) );
1520 sal_uInt16 nLevels = rRule.IsContinusNum() ? 1 : 9;
1521 for (sal_uInt16 nLvl = 0; nLvl < nLevels; ++nLvl)
1522 {
1523 const SwNumFormat &rFormat = rRule.Get(nLvl);
1524 if (SVX_NUM_BITMAP != rFormat.GetNumberingType())
1525 {
1526 continue;
1527 }
1528 const Graphic *pGraf = rFormat.GetBrush()? rFormat.GetBrush()->GetGraphic():nullptr;
1529 if ( pGraf )
1530 {
1531 bool bHas = false;
1532 for (const Graphic* p : m_vecBulletPic)
1533 {
1534 if (p->GetChecksum() == pGraf->GetChecksum())
1535 {
1536 bHas = true;
1537 break;
1538 }
1539 }
1540 if (!bHas)
1541 {
1542 Size aSize(pGraf->GetPrefSize());
1543 if (0 != aSize.Height() && 0 != aSize.Width())
1544 m_vecBulletPic.push_back(pGraf);
1545 }
1546 }
1547 }
1548 }
1549
1550 return m_vecBulletPic.size();
1551}
1552
1553void MSWordExportBase::BulletDefinitions()
1554{
1555 for (size_t i = 0; i < m_vecBulletPic.size(); ++i)
1556 {
1557 const MapMode aMapMode(MapUnit::MapTwip);
1558 const Graphic& rGraphic = *m_vecBulletPic[i];
1559 Size aSize(rGraphic.GetPrefSize());
1560 if (MapUnit::MapPixel == rGraphic.GetPrefMapMode().GetMapUnit())
1561 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapMode);
1562 else
1563 aSize = OutputDevice::LogicToLogic(aSize,rGraphic.GetPrefMapMode(), aMapMode);
1564
1565 if (0 != aSize.Height() && 0 != aSize.Width())
1566 AttrOutput().BulletDefinition(i, rGraphic, aSize);
1567 }
1568}
1569
1570//Export Graphic of Bullets
1571void WW8Export::ExportGrfBullet(const SwTextNode& rNd)
1572{
1573 int nCount = CollectGrfsOfBullets();
1574 if (nCount > 0)
1575 {
1576 SwPosition aPos(rNd);
1577 OUString aPicBullets("_PictureBullets");
1578 AppendBookmark(aPicBullets);
1579 for (int i = 0; i < nCount; i++)
1580 {
1581 ww8::Frame aFrame(*(m_vecBulletPic[i]), aPos);
1582 OutGrfBullets(aFrame);
1583 }
1584 AppendBookmark(aPicBullets);
1585 }
1586}
1587
1588static sal_uInt8 nAttrMagicIdx = 0;
1589void WW8Export::OutGrfBullets(const ww8::Frame & rFrame)
1590{
1591 if ( !m_pGrf || !m_pChpPlc || !pO )
1592 return;
1593
1594 m_pGrf->Insert(rFrame);
1595 m_pChpPlc->AppendFkpEntry( Strm().Tell(), pO->size(), pO->data() );
1596 pO->clear();
1597 // if links...
1598 WriteChar( char(1) );
1599
1600 sal_uInt8 aArr[ 22 ];
1601 sal_uInt8* pArr = aArr;
1602
1603 // sprmCFSpec
1604 Set_UInt16( pArr, 0x855 );
1605 Set_UInt8( pArr, 1 );
1606
1607 Set_UInt16( pArr, 0x083c );
1608 Set_UInt8( pArr, 0x81 );
1609
1610 // sprmCPicLocation
1611 Set_UInt16( pArr, 0x6a03 );
1612 Set_UInt32( pArr, GRF_MAGIC_3210x563412L );
1613
1614 //extern nAttrMagicIdx;
1615 --pArr;
1616 Set_UInt8( pArr, nAttrMagicIdx++ );
1617 m_pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
1618}
1619
1620int MSWordExportBase::GetGrfIndex(const SvxBrushItem& rBrush)
1621{
1622 int nIndex = -1;
1623
1624 const Graphic* pGraphic = rBrush.GetGraphic();
1625 if (pGraphic)
1626 {
1627 for (size_t i = 0; i < m_vecBulletPic.size(); ++i)
1628 {
1629 if (m_vecBulletPic[i]->GetChecksum() == pGraphic->GetChecksum())
1630 {
1631 nIndex = i;
1632 break;
1633 }
1634 }
1635 }
1636
1637 return nIndex;
1638}
1639
1640void WW8_WrtRedlineAuthor::Write( Writer& rWrt )
1641{
1642 WW8Export & rWW8Wrt = *(static_cast<SwWW8Writer&>(rWrt).m_pExport);
1643 rWW8Wrt.WriteAsStringTable(maAuthors, rWW8Wrt.pFib->m_fcSttbfRMark,
1644 rWW8Wrt.pFib->m_lcbSttbfRMark);
1645}
1646
1647sal_uInt16 WW8Export::AddRedlineAuthor( std::size_t nId )
1648{
1649 if( !m_pRedlAuthors )
1650 {
1651 m_pRedlAuthors = new WW8_WrtRedlineAuthor;
1652 m_pRedlAuthors->AddName("Unknown");
1653 }
1654 return m_pRedlAuthors->AddName( SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetRedlineAuthor( nId ) );
1655}
1656
1657void WW8Export::WriteAsStringTable(const std::vector<OUString>& rStrings,
1658 sal_Int32& rfcSttbf, sal_Int32& rlcbSttbf)
1659{
1660 sal_uInt16 n, nCount = static_cast< sal_uInt16 >(rStrings.size());
1661 if( !nCount )
1662 return;
1663
1664 // we have some Redlines found in the document -> the
1665 // Author Name Stringtable
1666 SvStream& rStrm = *pTableStrm;
1667 rfcSttbf = rStrm.Tell();
1668 SwWW8Writer::WriteShort( rStrm, -1 );
1669 SwWW8Writer::WriteLong( rStrm, nCount );
1670 for( n = 0; n < nCount; ++n )
1671 {
1672 const OUString& rNm = rStrings[n];
1673 SwWW8Writer::WriteShort( rStrm, rNm.getLength() );
1674 SwWW8Writer::WriteString16(rStrm, rNm, false);
1675 }
1676 rlcbSttbf = rStrm.Tell() - rfcSttbf;
1677}
1678
1679// WriteShort() sets at FilePos nPos the value nVal and seeks to the old
1680// FilePos. Used to insert lengths after the fact.
1681void SwWW8Writer::WriteShort( SvStream& rStrm, sal_uLong nPos, sal_Int16 nVal )
1682{
1683 sal_uInt64 nOldPos = rStrm.Tell(); // remember Pos
1684 rStrm.Seek( nPos );
1685 SwWW8Writer::WriteShort( rStrm, nVal );
1686 rStrm.Seek( nOldPos );
1687}
1688
1689void SwWW8Writer::WriteLong( SvStream& rStrm, sal_uLong nPos, sal_Int32 nVal )
1690{
1691 sal_uInt64 nOldPos = rStrm.Tell(); // remember Pos
1692 rStrm.Seek( nPos );
1693 SwWW8Writer::WriteLong( rStrm, nVal );
1694 rStrm.Seek( nOldPos );
1695}
1696
1697void SwWW8Writer::InsUInt16(ww::bytes &rO, sal_uInt16 n)
1698{
1699 SVBT16 nL;
1700 ShortToSVBT16( n, nL );
1701 rO.push_back(nL[0]);
1702 rO.push_back(nL[1]);
1703}
1704
1705void SwWW8Writer::InsUInt32(ww::bytes &rO, sal_uInt32 n)
1706{
1707 SVBT32 nL;
1708 UInt32ToSVBT32( n, nL );
1709 rO.push_back(nL[0]);
1710 rO.push_back(nL[1]);
1711 rO.push_back(nL[2]);
1712 rO.push_back(nL[3]);
1713}
1714
1715void SwWW8Writer::InsAsString16(ww::bytes &rO, const OUString& rStr)
1716{
1717 const sal_Unicode* pStr = rStr.getStr();
1718 for (sal_Int32 n = 0, nLen = rStr.getLength(); n < nLen; ++n, ++pStr)
1719 SwWW8Writer::InsUInt16( rO, *pStr );
1720}
1721
1722void SwWW8Writer::InsAsString8(ww::bytes &rO, const OUString& rStr,
1723 rtl_TextEncoding eCodeSet)
1724{
1725 OString sTmp(OUStringToOString(rStr, eCodeSet));
1726 const char *pStart = sTmp.getStr();
1727 const char *pEnd = pStart + sTmp.getLength();
1728
1729 rO.insert( rO.end(), pStart, pEnd );
1730}
1731
1732void SwWW8Writer::WriteString16(SvStream& rStrm, const OUString& rStr,
1733 bool bAddZero)
1734{
1735 ww::bytes aBytes;
1736 SwWW8Writer::InsAsString16(aBytes, rStr);
1737 if (bAddZero)
1738 SwWW8Writer::InsUInt16(aBytes, 0);
1739 //vectors are guaranteed to have contiguous memory, so we can do
1740 //this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1741 if (!aBytes.empty())
1742 rStrm.WriteBytes(aBytes.data(), aBytes.size());
1743}
1744
1745void SwWW8Writer::WriteString_xstz(SvStream& rStrm, const OUString& rStr, bool bAddZero)
1746{
1747 ww::bytes aBytes;
1748 SwWW8Writer::InsUInt16(aBytes, rStr.getLength());
1749 SwWW8Writer::InsAsString16(aBytes, rStr);
1750 if (bAddZero)
1751 SwWW8Writer::InsUInt16(aBytes, 0);
1752 rStrm.WriteBytes(aBytes.data(), aBytes.size());
1753}
1754
1755void SwWW8Writer::WriteString8(SvStream& rStrm, const OUString& rStr,
1756 bool bAddZero, rtl_TextEncoding eCodeSet)
1757{
1758 ww::bytes aBytes;
1759 SwWW8Writer::InsAsString8(aBytes, rStr, eCodeSet);
1760 if (bAddZero)
1761 aBytes.push_back(0);
1762 //vectors are guaranteed to have contiguous memory, so we can do
1763 ////this while migrating away from WW8Bytes. Meyers Effective STL, item 16
1764 if (!aBytes.empty())
1765 rStrm.WriteBytes(aBytes.data(), aBytes.size());
1766}
1767
1768void WW8Export::WriteStringAsPara( const OUString& rText )
1769{
1770 if( !rText.isEmpty() )
1771 OutSwString(rText, 0, rText.getLength());
1772 WriteCR(); // CR thereafter
1773
1774 ww::bytes aArr;
1775 SwWW8Writer::InsUInt16( aArr, 0/*nStyleId*/ );
1776 if( m_bOutTable )
1777 { // Tab-Attr
1778 // sprmPFInTable
1779 SwWW8Writer::InsUInt16( aArr, NS_sprm::PFInTable::val );
1780 aArr.push_back( 1 );
1781 }
1782
1783 sal_uInt64 nPos = Strm().Tell();
1784 m_pPapPlc->AppendFkpEntry( nPos, aArr.size(), aArr.data() );
1785 m_pChpPlc->AppendFkpEntry( nPos );
1786}
1787
1788void MSWordExportBase::WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_uInt8 nTTyp )
1789{
1790 sal_uInt8 nOldTyp = m_nTextTyp;
1791 m_nTextTyp = nTTyp;
1792 auto const pOldPam = m_pCurPam; //!! Simply shifting the PaM without restoring should do the job too
1793 sal_uLong nOldStart = m_nCurStart;
1794 sal_uLong nOldEnd = m_nCurEnd;
1795 SwPaM* pOldEnd = m_pOrigPam;
1796 bool bOldPageDescs = m_bOutPageDescs;
1797 m_bOutPageDescs = false;
1798 if ( nTTyp == TXT_FTN || nTTyp == TXT_EDN )
1799 m_bAddFootnoteTab = true; // enable one aesthetic tab for this footnote
1800
1801 SetCurPam(nStart, nEnd);
1802
1803 // clear linked textboxes since old ones can't be linked to frames in this section
1804 m_aLinkedTextboxesHelper.clear();
1805
1806 // tdf#106261 Reset table infos, otherwise the depth of the cells will be
1807 // incorrect, in case the header/footer had table(s) and we try to export
1808 // the same table second time.
1809 ww8::WW8TableInfo::Pointer_t pOldTableInfo = m_pTableInfo;
1810 m_pTableInfo = std::make_shared<ww8::WW8TableInfo>();
1811
1812 WriteText();
1813
1814 m_pTableInfo = pOldTableInfo;
1815
1816 m_bOutPageDescs = bOldPageDescs;
1817 m_pCurPam = pOldPam; // delete Pam
1818 m_nCurStart = nOldStart;
1819 m_nCurEnd = nOldEnd;
1820 m_pOrigPam = pOldEnd;
1821 m_nTextTyp = nOldTyp;
1822}
1823
1824void WW8Export::OutSwString(const OUString& rStr, sal_Int32 nStt,
1825 sal_Int32 const nLen)
1826
1827{
1828 SAL_INFO( "sw.ww8.level2", "<OutSwString>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "<OutSwString>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1828" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<OutSwString>"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"<OutSwString>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1828" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "<OutSwString>") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1828" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<OutSwString>"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"<OutSwString>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1828" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1829
1830 if( nLen )
1831 {
1832 if( nStt || nLen != rStr.getLength() )
1833 {
1834 OUString sOut( rStr.copy( nStt, nLen ) );
1835
1836 SAL_INFO( "sw.ww8.level2", sOut )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << sOut) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1836" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << sOut), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << sOut; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1836" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << sOut) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1836" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << sOut), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << sOut; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1836" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1837
1838 SwWW8Writer::WriteString16(Strm(), sOut, false);
1839 }
1840 else
1841 {
1842 SAL_INFO( "sw.ww8.level2", rStr )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << rStr) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1842" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << rStr), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << rStr; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1842" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << rStr) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1842" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << rStr), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << rStr; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1842" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1843
1844 SwWW8Writer::WriteString16(Strm(), rStr, false);
1845 }
1846 }
1847
1848 SAL_INFO( "sw.ww8.level2", "</OutSwString>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "</OutSwString>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1848" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutSwString>"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"</OutSwString>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1848" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "</OutSwString>") == 1) { ::sal_detail_log(
(::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1848" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutSwString>"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"</OutSwString>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1848" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1849}
1850
1851void WW8Export::WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
1852{
1853 if (pTableTextNodeInfoInner && pTableTextNodeInfoInner->getDepth() == 1 && pTableTextNodeInfoInner->isEndOfCell())
1854 WriteChar('\007');
1855 else
1856 WriteChar( '\015' );
1857
1858 m_pPiece->SetParaBreak();
1859}
1860
1861void WW8Export::WriteChar( sal_Unicode c )
1862{
1863 Strm().WriteUInt16( c );
1864}
1865
1866void MSWordExportBase::SetCurPam(sal_uLong nStt, sal_uLong nEnd)
1867{
1868 m_nCurStart = nStt;
1869 m_nCurEnd = nEnd;
1870 m_pCurPam = Writer::NewUnoCursor( m_rDoc, nStt, nEnd );
1871
1872 // Recognize tables in special cases
1873 if ( nStt != m_pCurPam->GetMark()->nNode.GetIndex() &&
1874 m_rDoc.GetNodes()[ nStt ]->IsTableNode() )
1875 {
1876 m_pCurPam->GetMark()->nNode = nStt;
1877 }
1878
1879 m_pOrigPam = m_pCurPam.get(); // ???
1880 m_pCurPam->Exchange();
1881}
1882
1883void MSWordExportBase::SaveData( sal_uLong nStt, sal_uLong nEnd )
1884{
1885 MSWordSaveData aData;
1886
1887 // WW8Export only stuff - zeroed here not to issue warnings
1888 aData.pOOld = nullptr;
1889
1890 // Common stuff
1891 aData.pOldPam = m_pCurPam;
1892 aData.pOldEnd = m_pOrigPam;
1893 aData.pOldFlyFormat = m_pParentFrame;
1894 aData.pOldPageDesc = m_pCurrentPageDesc;
1895
1896 aData.pOldFlyOffset = m_pFlyOffset;
1897 aData.eOldAnchorType = m_eNewAnchorType;
1898
1899 aData.bOldOutTable = m_bOutTable;
1900 aData.bOldFlyFrameAttrs = m_bOutFlyFrameAttrs;
1901 aData.bOldStartTOX = m_bStartTOX;
1902 aData.bOldInWriteTOX = m_bInWriteTOX;
1903
1904 SetCurPam(nStt, nEnd);
1905
1906 m_bOutTable = false;
1907 // Caution: bIsInTable should not be set here
1908 m_bOutFlyFrameAttrs = false;
1909 m_bStartTOX = false;
1910 m_bInWriteTOX = false;
1911
1912 m_aSaveData.push( std::move(aData) );
1913}
1914
1915void MSWordExportBase::RestoreData()
1916{
1917 MSWordSaveData &rData = m_aSaveData.top();
1918
1919 m_pCurPam = rData.pOldPam;
1920 m_nCurStart = rData.nOldStart;
1921 m_nCurEnd = rData.nOldEnd;
1922 m_pOrigPam = rData.pOldEnd;
1923
1924 m_bOutTable = rData.bOldOutTable;
1925 m_bOutFlyFrameAttrs = rData.bOldFlyFrameAttrs;
1926 m_bStartTOX = rData.bOldStartTOX;
1927 m_bInWriteTOX = rData.bOldInWriteTOX;
1928
1929 m_pParentFrame = rData.pOldFlyFormat;
1930 m_pCurrentPageDesc = rData.pOldPageDesc;
1931
1932 m_eNewAnchorType = rData.eOldAnchorType;
1933 m_pFlyOffset = rData.pOldFlyOffset;
1934
1935 m_aSaveData.pop();
1936}
1937
1938void WW8Export::SaveData( sal_uLong nStt, sal_uLong nEnd )
1939{
1940 MSWordExportBase::SaveData( nStt, nEnd );
1941
1942 MSWordSaveData &rData = m_aSaveData.top();
1943
1944 if ( !pO->empty() )
1945 {
1946 rData.pOOld = std::move(pO);
1947 pO.reset(new ww::bytes);
1948 }
1949 else
1950 rData.pOOld = nullptr; // reuse pO
1951
1952 rData.bOldWriteAll = GetWriter().m_bWriteAll;
1953 GetWriter().m_bWriteAll = true;
1954}
1955
1956void WW8Export::RestoreData()
1957{
1958 MSWordSaveData &rData = m_aSaveData.top();
1959
1960 GetWriter().m_bWriteAll = rData.bOldWriteAll;
1961
1962 OSL_ENSURE( pO->empty(), "pO is not empty in WW8Export::RestoreData()" )do { if (true && (!(pO->empty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "1962" ": "), "%s", "pO is not empty in WW8Export::RestoreData()"
); } } while (false)
;
1963 if ( rData.pOOld )
1964 {
1965 pO = std::move(rData.pOOld);
1966 }
1967
1968 MSWordExportBase::RestoreData();
1969}
1970
1971void WW8AttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1972{
1973 sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
1974
1975 if ( nDepth <= 0 )
1976 return;
1977
1978 /* Cell */
1979 m_rWW8Export.InsUInt16( NS_sprm::PFInTable::val );
1980 m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
1981 m_rWW8Export.InsUInt16( NS_sprm::PItap::val );
1982 m_rWW8Export.InsUInt32( nDepth );
1983
1984 if ( nDepth > 1 && pTableTextNodeInfoInner->isEndOfCell() )
1985 {
1986 m_rWW8Export.InsUInt16( NS_sprm::PFInnerTableCell::val );
1987 m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
1988 }
1989}
1990
1991void WW8AttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1992{
1993 sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
1994
1995 if ( nDepth <= 0 )
1996 return;
1997
1998 /* Row */
1999 if ( !pTableTextNodeInfoInner->isEndOfLine() )
2000 return;
2001
2002 m_rWW8Export.InsUInt16( NS_sprm::PFInTable::val );
2003 m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2004
2005 if ( nDepth == 1 )
2006 {
2007 m_rWW8Export.InsUInt16( NS_sprm::PFTtp::val );
2008 m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2009 }
2010
2011 m_rWW8Export.InsUInt16( NS_sprm::PItap::val );
2012 m_rWW8Export.InsUInt32( nDepth );
2013
2014 if ( nDepth > 1 )
2015 {
2016 m_rWW8Export.InsUInt16( NS_sprm::PFInnerTableCell::val );
2017 m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2018 m_rWW8Export.InsUInt16( NS_sprm::PFInnerTtp::val );
2019 m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2020 }
2021
2022 // Most of these are per-row definitions, not per-table.
2023 // WW8 has no explicit table start/end markup,
2024 // simply rows with the same table properties that are grouped together as a table.
2025 TableBidi( pTableTextNodeInfoInner );
2026 TableOrientation( pTableTextNodeInfoInner );
2027 TableSpacing( pTableTextNodeInfoInner );
2028 TableDefinition( pTableTextNodeInfoInner ); //per row definitions
2029 TableHeight( pTableTextNodeInfoInner ); //per row definitions
2030 TableBackgrounds( pTableTextNodeInfoInner ); //per row definitions
2031 // Since this isEndOfLine, cell margin defaults for each row come from last column.
2032 TableDefaultBorders( pTableTextNodeInfoInner ); //per row definitions
2033 TableCanSplit( pTableTextNodeInfoInner ); //per row definitions
2034 TableVerticalCell( pTableTextNodeInfoInner ); //per row definitions
2035 TableCellBorders( pTableTextNodeInfoInner ); //per row definitions
2036}
2037
2038static sal_uInt16 lcl_TCFlags(SwDoc &rDoc, const SwTableBox * pBox, sal_Int32 nRowSpan)
2039{
2040 sal_uInt16 nFlags = 0;
2041
2042 if (nRowSpan > 1)
2043 nFlags |= (3 << 5);
2044 else if (nRowSpan < 0)
2045 nFlags |= (1 << 5);
2046
2047 if (pBox != nullptr)
2048 {
2049 const SwFrameFormat * pFormat = pBox->GetFrameFormat();
2050 switch (pFormat->GetVertOrient().GetVertOrient())
2051 {
2052 case text::VertOrientation::CENTER:
2053 nFlags |= (1 << 7);
2054 break;
2055 case text::VertOrientation::BOTTOM:
2056 nFlags |= (2 << 7);
2057 break;
2058 default:
2059 break;
2060 }
2061 const SwStartNode * pSttNd = pBox->GetSttNd();
2062 if(pSttNd)
2063 {
2064 SwNodeIndex aIdx( *pSttNd );
2065 const SwContentNode * pCNd = pSttNd->GetNodes().GoNext( &aIdx );
2066 if( pCNd && pCNd->IsTextNode())
2067 {
2068 SfxItemSet aCoreSet(rDoc.GetAttrPool(), svl::Items<RES_CHRATR_ROTATE, RES_CHRATR_ROTATE>{});
2069 static_cast<const SwTextNode*>(pCNd)->GetParaAttr(aCoreSet,
2070 0, static_cast<const SwTextNode*>(pCNd)->GetText().getLength());
2071 const SfxPoolItem * pRotItem;
2072 if ( SfxItemState::SET == aCoreSet.GetItemState(RES_CHRATR_ROTATE, true, &pRotItem))
2073 {
2074 const SvxCharRotateItem * pRotate = static_cast<const SvxCharRotateItem*>(pRotItem);
2075 if(pRotate && pRotate->GetValue() == 900)
2076 {
2077 nFlags = nFlags | 0x0004 | 0x0008;
2078 }
2079 else if(pRotate && pRotate->GetValue() == 2700 )
2080 {
2081 nFlags = nFlags | 0x0004 | 0x0010;
2082 }
2083 }
2084 }
2085 }
2086 }
2087
2088 return nFlags;
2089}
2090
2091void WW8AttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2092{
2093 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2094 const SwTableLine * pTabLine = pTabBox->GetUpper();
2095 const SwTableBoxes & rTableBoxes = pTabLine->GetTabBoxes();
2096
2097 sal_uInt8 nBoxes = rTableBoxes.size();
2098 for ( sal_uInt8 n = 0; n < nBoxes; n++ )
2099 {
2100 const SwTableBox * pTabBox1 = rTableBoxes[n];
2101 const SwFrameFormat * pFrameFormat = pTabBox1->GetFrameFormat();
2102
2103 // Map from our SvxFrameDirection to WW8 TextFlow.
2104 sal_uInt16 nTextFlow = 0;
2105 switch (m_rWW8Export.TrueFrameDirection(*pFrameFormat))
2106 {
2107 case SvxFrameDirection::Vertical_RL_TB:
2108 nTextFlow = 5;
2109 break;
2110 case SvxFrameDirection::Vertical_LR_BT:
2111 nTextFlow = 3;
2112 break;
2113 default:
2114 break;
2115 }
2116
2117 if (nTextFlow != 0)
2118 {
2119 m_rWW8Export.InsUInt16( NS_sprm::TTextFlow::val );
2120 m_rWW8Export.pO->push_back( n ); //start range
2121 m_rWW8Export.pO->push_back( sal_uInt8(n + 1) ); //end range
2122 m_rWW8Export.InsUInt16(nTextFlow);
2123 }
2124 }
2125}
2126
2127void WW8AttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2128{
2129 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2130 const SwTableLine * pTabLine = pTabBox->GetUpper();
2131 const SwFrameFormat * pLineFormat = pTabLine->GetFrameFormat();
2132
2133 /*
2134 By default the row can be split in word, and now in writer we have a
2135 feature equivalent to this, Word stores 1 for fCantSplit if the row
2136 cannot be split, we set true if we can split it. An example is #i4569#
2137 */
2138
2139 const SwFormatRowSplit& rSplittable = pLineFormat->GetRowSplit();
2140 sal_uInt8 nCantSplit = (!rSplittable.GetValue()) ? 1 : 0;
2141 m_rWW8Export.InsUInt16( NS_sprm::TFCantSplit::val );
2142 m_rWW8Export.pO->push_back( nCantSplit );
2143 m_rWW8Export.InsUInt16( NS_sprm::TFCantSplit90::val ); // also write fCantSplit90
2144 m_rWW8Export.pO->push_back( nCantSplit );
2145}
2146
2147void WW8AttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2148{
2149 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2150 const SwFrameFormat * pFrameFormat = pTable->GetFrameFormat();
2151
2152 if ( m_rWW8Export.TrueFrameDirection(*pFrameFormat) == SvxFrameDirection::Horizontal_RL_TB )
2153 {
2154 m_rWW8Export.InsUInt16( NS_sprm::TFBiDi::val );
2155 m_rWW8Export.InsUInt16( 1 );
2156 }
2157}
2158
2159void WW8AttributeOutput::TableRowRedline( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
2160{
2161}
2162
2163void WW8AttributeOutput::TableCellRedline( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
2164{
2165}
2166
2167void WW8AttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2168{
2169 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2170 const SwTableLine * pTabLine = pTabBox->GetUpper();
2171 const SwFrameFormat * pLineFormat = pTabLine->GetFrameFormat();
2172
2173 // output line height sprmTDyaRowHeight
2174 long nHeight = 0;
2175 const SwFormatFrameSize& rLSz = pLineFormat->GetFrameSize();
2176 if ( SwFrameSize::Variable != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
2177 {
2178 if ( SwFrameSize::Minimum == rLSz.GetHeightSizeType() )
2179 nHeight = rLSz.GetHeight();
2180 else
2181 nHeight = -rLSz.GetHeight();
2182 }
2183
2184 if ( nHeight )
2185 {
2186 m_rWW8Export.InsUInt16( NS_sprm::TDyaRowHeight::val );
2187 m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(nHeight) );
2188 }
2189
2190}
2191
2192void WW8AttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2193{
2194 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2195
2196 const SwFrameFormat *pFormat = pTable->GetFrameFormat();
2197 if ( !pFormat )
2198 {
2199 SAL_WARN( "sw.ww8", "FrameFormat is nil" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "FrameFormat is nil")
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2199" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FrameFormat is nil"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"FrameFormat is nil"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2199" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FrameFormat is nil") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2199" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FrameFormat is nil"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"FrameFormat is nil"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2199" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2200 return;
2201 }
2202
2203 const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient();
2204 const SwFormatVertOrient &rVert = pFormat->GetVertOrient();
2205
2206 if (
2207 !((text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2208 text::RelOrientation::FRAME == rHori.GetRelationOrient())
2209 &&
2210 (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2211 text::RelOrientation::FRAME == rVert.GetRelationOrient()))
2212 )
2213 return;
2214
2215 const bool bIsRTL = m_rWW8Export.TrueFrameDirection(*pFormat) == SvxFrameDirection::Horizontal_RL_TB;
2216 sal_Int16 eHOri = rHori.GetHoriOrient();
2217 switch (eHOri)
2218 {
2219 case text::HoriOrientation::CENTER:
2220 m_rWW8Export.InsUInt16( NS_sprm::TJc::val ); //logical orientation required for MSO
2221 m_rWW8Export.InsUInt16( 1 );
2222 m_rWW8Export.InsUInt16( NS_sprm::TJc90::val ); //physical orientation required for LO
2223 m_rWW8Export.InsUInt16( 1 );
2224 break;
2225 case text::HoriOrientation::RIGHT:
2226 m_rWW8Export.InsUInt16( NS_sprm::TJc90::val ); //required for LO
2227 m_rWW8Export.InsUInt16( 2 );
2228 if ( !bIsRTL )
2229 {
2230 m_rWW8Export.InsUInt16( NS_sprm::TJc::val ); //required for MSO
2231 m_rWW8Export.InsUInt16( 2 );
2232 }
2233 break;
2234 case text::HoriOrientation::LEFT:
2235 if ( bIsRTL )
2236 {
2237 m_rWW8Export.InsUInt16( NS_sprm::TJc::val ); //required for MSO
2238 m_rWW8Export.InsUInt16( 2 );
2239 }
2240 break;
2241 case text::HoriOrientation::LEFT_AND_WIDTH:
2242 // Width can only be specified for the LOGICAL left, so in RTL, that is always PHYSICAL right
2243 if ( bIsRTL )
2244 {
2245 m_rWW8Export.InsUInt16( NS_sprm::TJc90::val ); //required for LO
2246 m_rWW8Export.InsUInt16( 2 );
2247 }
2248 break;
2249 default:
2250 break;
2251 }
2252}
2253
2254void WW8AttributeOutput::TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
2255{
2256 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2257 const SwTableFormat* pTableFormat = pTable->GetFrameFormat();
2258
2259
2260 // Writing these SPRM's will make the table a floating one, so only write
2261 // them in case the table is already inside a frame.
2262 if (!(pTableFormat != nullptr && pTable->GetTableNode()->GetFlyFormat()))
2263 return;
2264
2265 const SvxULSpaceItem & rUL = pTableFormat->GetULSpace();
2266
2267 if (rUL.GetUpper() > 0)
2268 {
2269 sal_uInt8 const nPadding = 2;
2270 sal_uInt8 const nPcVert = 0;
2271 sal_uInt8 const nPcHorz = 0;
2272
2273 sal_uInt8 const nTPc = (nPadding << 4) | (nPcVert << 2) | nPcHorz;
2274
2275 m_rWW8Export.InsUInt16(NS_sprm::TPc::val);
2276 m_rWW8Export.pO->push_back( nTPc );
2277
2278 m_rWW8Export.InsUInt16(NS_sprm::TDyaAbs::val);
2279 m_rWW8Export.InsUInt16(rUL.GetUpper());
2280
2281 m_rWW8Export.InsUInt16(NS_sprm::TDyaFromText::val);
2282 m_rWW8Export.InsUInt16(rUL.GetUpper());
2283 }
2284
2285 if (rUL.GetLower() > 0)
2286 {
2287 m_rWW8Export.InsUInt16(NS_sprm::TDyaFromTextBottom::val);
2288 m_rWW8Export.InsUInt16(rUL.GetLower());
2289 }
2290}
2291
2292void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2293{
2294 const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2295
2296 if ( pTable->GetRowsToRepeat() > pTableTextNodeInfoInner->getRow() )
2297 {
2298 m_rWW8Export.InsUInt16( NS_sprm::TTableHeader::val );
2299 m_rWW8Export.pO->push_back( 1 );
2300 }
2301
2302 ww8::TableBoxVectorPtr pTableBoxes =
2303 pTableTextNodeInfoInner->getTableBoxesOfRow();
2304 // number of cell written
2305 sal_uInt32 nBoxes = pTableBoxes->size();
2306 assert(nBoxes <= ww8::MAXTABLECELLS)(static_cast <bool> (nBoxes <= ww8::MAXTABLECELLS) ?
void (0) : __assert_fail ("nBoxes <= ww8::MAXTABLECELLS",
"/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
, 2306, __extension__ __PRETTY_FUNCTION__))
;
2307
2308 // sprm header
2309 m_rWW8Export.InsUInt16( NS_sprm::TDefTable::val );
2310 sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
2311 m_rWW8Export.InsUInt16( nSprmSize ); // length
2312
2313 // number of boxes
2314 m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(nBoxes) );
2315
2316 /* cells */
2317 /*
2318 ALWAYS relative when text::HoriOrientation::NONE (nPageSize + ( nPageSize / 10 )) < nTableSz,
2319 in that case the cell width's and table width's are not real. The table
2320 width is maxed and cells relative, so we need the frame (generally page)
2321 width that the table is in to work out the true widths.
2322 */
2323 //const bool bNewTableModel = pTable->IsNewModel();
2324 const SwFrameFormat *pFormat = pTable->GetFrameFormat();
2325 if ( !pFormat )
2326 {
2327 SAL_WARN( "sw.ww8", "FrameFormat is nil" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "FrameFormat is nil")
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2327" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FrameFormat is nil"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"FrameFormat is nil"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2327" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FrameFormat is nil") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2327" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FrameFormat is nil"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"FrameFormat is nil"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2327" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2328 return;
2329 }
2330
2331 const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient();
2332 const SwFormatVertOrient &rVert = pFormat->GetVertOrient();
2333
2334 SwTwips nTableOffset = 0;
2335
2336 if (
2337 (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2338 text::RelOrientation::FRAME == rHori.GetRelationOrient())
2339 &&
2340 (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2341 text::RelOrientation::FRAME == rVert.GetRelationOrient())
2342 )
2343 {
2344 sal_Int16 eHOri = rHori.GetHoriOrient();
2345 switch ( eHOri )
2346 {
2347 case text::HoriOrientation::CENTER:
2348 case text::HoriOrientation::RIGHT:
2349 break;
2350
2351 default:
2352 nTableOffset = rHori.GetPos();
2353 const SvxLRSpaceItem& rLRSp = pFormat->GetLRSpace();
2354 nTableOffset += rLRSp.GetLeft();
2355
2356 // convert offset to be measured from right margin in right-to-left tables
2357 if ( nTableOffset && m_rWW8Export.TrueFrameDirection(*pFormat) == SvxFrameDirection::Horizontal_RL_TB )
2358 {
2359 SwTwips nLeftPageMargin, nRightPageMargin;
2360 const SwTwips nPageSize = m_rWW8Export.CurrentPageWidth(nLeftPageMargin, nRightPageMargin);
2361 const SwTwips nTableWidth = pFormat->GetFrameSize().GetWidth();
2362 nTableOffset = nPageSize - nLeftPageMargin - nRightPageMargin - nTableWidth - nTableOffset;
2363 }
2364 break;
2365 }
2366 }
2367
2368 m_rWW8Export.InsInt16( nTableOffset );
2369
2370 ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
2371 for ( const auto nCol : *pGridCols )
2372 {
2373 m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(nCol) + nTableOffset );
2374 }
2375
2376 /* TCs */
2377 ww8::RowSpansPtr pRowSpans = pTableTextNodeInfoInner->getRowSpansOfRow();
2378 ww8::RowSpans::const_iterator aItRowSpans = pRowSpans->begin();
2379
2380 for (const SwTableBox * pTabBox1 : *pTableBoxes)
2381 {
2382 sal_uInt16 npOCount = m_rWW8Export.pO->size();
2383
2384 const SwFrameFormat * pBoxFormat = nullptr;
2385 if (pTabBox1 != nullptr)
2386 pBoxFormat = pTabBox1->GetFrameFormat();
2387
2388 sal_uInt16 nFlags =
2389 lcl_TCFlags(m_rWW8Export.m_rDoc, pTabBox1, *aItRowSpans);
2390 m_rWW8Export.InsUInt16( nFlags );
2391
2392 static sal_uInt8 aNullBytes[] = { 0x0, 0x0 };
2393
2394 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), aNullBytes, aNullBytes+2 ); // dummy
2395 if (pBoxFormat != nullptr)
2396 {
2397 const SvxBoxItem & rBoxItem = pBoxFormat->GetBox();
2398
2399 WW8Export::Out_SwFormatTableBox( *m_rWW8Export.pO, &rBoxItem ); // 8/16 Byte
2400 }
2401 else
2402 WW8Export::Out_SwFormatTableBox( *m_rWW8Export.pO, nullptr); // 8/16 Byte
2403
2404 SAL_INFO( "sw.ww8.level2", "<tclength>" << ( m_rWW8Export.pO->size() - npOCount ) << "</tclength>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "<tclength>" <<
( m_rWW8Export.pO->size() - npOCount ) << "</tclength>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2404" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<tclength>" << ( m_rWW8Export
.pO->size() - npOCount ) << "</tclength>"), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "<tclength>" << ( m_rWW8Export.pO->size
() - npOCount ) << "</tclength>"; ::sal::detail::
log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2404" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "<tclength>" << ( m_rWW8Export.pO->
size() - npOCount ) << "</tclength>") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2404" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<tclength>" << ( m_rWW8Export
.pO->size() - npOCount ) << "</tclength>"), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "<tclength>" << ( m_rWW8Export.pO->size
() - npOCount ) << "</tclength>"; ::sal::detail::
log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2404" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2405 ++aItRowSpans;
2406 }
2407
2408 int nWidthPercent = pFormat->GetFrameSize().GetWidthPercent();
2409 // Width is in fiftieths of a percent. For sprmTTableWidth, must be non-negative and 600% max
2410 if ( nWidthPercent > 0 && nWidthPercent <= 600 )
2411 {
2412 m_rWW8Export.InsUInt16( NS_sprm::TTableWidth::val );
2413 m_rWW8Export.pO->push_back( sal_uInt8/*ftsPercent*/ (2) );
2414 m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(nWidthPercent) * 50 );
2415 }
2416}
2417
2418ww8::GridColsPtr AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner )
2419{
2420 return pTableTextNodeInfoInner->getGridColsOfRow(*this);
2421}
2422
2423ww8::WidthsPtr AttributeOutputBase::GetColumnWidths( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner )
2424{
2425 // Get the column widths based on ALL the rows, not just the current row
2426 return pTableTextNodeInfoInner->getGridColsOfRow(*this, true);
2427}
2428
2429void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner const * pTableTextNodeInfoInner, long& rPageSize, bool& rRelBoxSize )
2430{
2431 long nPageSize = 0;
2432
2433 const SwNode *pTextNd = pTableTextNodeInfoInner->getNode( );
2434 const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
2435
2436 const SwFrameFormat *pFormat = pTable->GetFrameFormat();
2437 if ( !pFormat )
2438 {
2439 SAL_WARN( "sw.ww8", "FrameFormat is nil" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "FrameFormat is nil")
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2439" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FrameFormat is nil"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"FrameFormat is nil"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2439" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FrameFormat is nil") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2439" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FrameFormat is nil"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"FrameFormat is nil"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2439" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2440 return;
2441 }
2442
2443 const SwFormatFrameSize &rSize = pFormat->GetFrameSize();
2444 int nWidthPercent = rSize.GetWidthPercent();
2445 bool bManualAligned = pFormat->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::NONE;
2446 if ( (pFormat->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::FULL) || bManualAligned )
2447 nWidthPercent = 100;
2448 bool bRelBoxSize = nWidthPercent != 0;
2449 unsigned long nTableSz = static_cast<unsigned long>(rSize.GetWidth());
2450 if (nTableSz > USHRT_MAX(32767 *2 +1)/2 && !bRelBoxSize)
2451 {
2452 OSL_ENSURE(bRelBoxSize, "huge table width but not relative, suspicious")do { if (true && (!(bRelBoxSize))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2452" ": "), "%s", "huge table width but not relative, suspicious"
); } } while (false)
;
2453 bRelBoxSize = true;
2454 }
2455
2456 if ( bRelBoxSize )
2457 {
2458 Point aPt;
2459 SwRect aRect( pFormat->FindLayoutRect( false, &aPt ) );
2460 if ( aRect.IsEmpty() )
2461 {
2462 // Then fetch the page width without margins!
2463 const SwFrameFormat* pParentFormat =
2464 GetExport().m_pParentFrame ?
2465 &(GetExport().m_pParentFrame->GetFrameFormat()) :
2466 GetExport().m_rDoc.GetPageDesc(0).GetPageFormatOfNode(*pTextNd, false);
2467 aRect = pParentFormat->FindLayoutRect(true);
2468 nPageSize = aRect.Width();
2469 if ( 0 == nPageSize )
2470 {
2471 const SvxLRSpaceItem& rLR = pParentFormat->GetLRSpace();
2472 nPageSize = pParentFormat->GetFrameSize().GetWidth() - rLR.GetLeft()
2473 - rLR.GetRight();
2474 }
2475 }
2476 else
2477 {
2478 nPageSize = aRect.Width();
2479 if ( bManualAligned )
2480 {
2481 // #i37571# For manually aligned tables
2482 const SvxLRSpaceItem &rLR = pFormat->GetLRSpace();
2483 nPageSize -= (rLR.GetLeft() + rLR.GetRight());
2484 }
2485
2486 }
2487
2488 if ( nWidthPercent )
2489 {
2490 nPageSize *= nWidthPercent;
2491 nPageSize /= 100;
2492 }
2493 else
2494 SAL_WARN( "sw.ww8", "nWidthPercent is zero" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "nWidthPercent is zero"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2494" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "nWidthPercent is zero"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"nWidthPercent is zero"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2494" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "nWidthPercent is zero") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2494" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "nWidthPercent is zero"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"nWidthPercent is zero"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2494" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2495 }
2496 else
2497 {
2498 // As the table width is not relative, the TablePageSize equals its width
2499 nPageSize = nTableSz;
2500 }
2501
2502 rPageSize = nPageSize;
2503 rRelBoxSize = bRelBoxSize;
2504}
2505
2506void WW8AttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2507{
2508 // This function name is misleading because it is not a table default, but a row default,
2509 // and it also only sets default cell margins (aka border padding).
2510 // The specs suggest there is no way to define default border lines/colors.
2511 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2512 const SwFrameFormat * pFrameFormat = pTabBox->GetFrameFormat();
2513
2514 static const SvxBoxItemLine aBorders[] =
2515 {
2516 SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT,
2517 SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT
2518 };
2519
2520 // Set row default cell margins using this last cell in the row
2521 for ( int i = 0; i < 4; ++i )
2522 {
2523 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::TCellPaddingDefault::val );
2524 m_rWW8Export.pO->push_back( sal_uInt8(6) );
2525 m_rWW8Export.pO->push_back( sal_uInt8(0) );
2526 m_rWW8Export.pO->push_back( sal_uInt8(1) );
2527 m_rWW8Export.pO->push_back( sal_uInt8(1 << i) );
2528 m_rWW8Export.pO->push_back( sal_uInt8(3) );
2529
2530 SwWW8Writer::InsUInt16( *m_rWW8Export.pO,
2531 pFrameFormat->GetBox().GetDistance( aBorders[i] ) );
2532 }
2533}
2534
2535void WW8AttributeOutput::TableCellBorders(
2536 ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner )
2537{
2538 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2539 const SwTableLine * pTabLine = pTabBox->GetUpper();
2540 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2541 sal_uInt8 nBoxes = std::min<size_t>(rTabBoxes.size(), 255);
2542 const SvxBoxItem * pLastBox = nullptr;
2543 sal_uInt8 nSeqStart = 0; // start of sequence of cells with same borders
2544
2545 static const SvxBoxItemLine aBorders[] =
2546 {
2547 SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT,
2548 SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT
2549 };
2550
2551 sal_uInt16 nDefaultMargin[4] = {31681, 31681, 31681, 31681}; // outside of documented valid range
2552 // last column in each row defines the row default in TableRowDefaultBorders()
2553 if ( nBoxes && rTabBoxes.size() == nBoxes )
2554 {
2555 const SvxBoxItem& rBox = rTabBoxes[ nBoxes-1 ]->GetFrameFormat()->GetBox();
2556 for ( int i = 0; i < 4; ++i )
2557 nDefaultMargin[i] = rBox.GetDistance( aBorders[i] );
2558 }
2559
2560 // Detect sequences of cells which have the same borders, and output
2561 // a border description for each such cell range.
2562 for ( unsigned n = 0; n <= nBoxes; ++n )
2563 {
2564 const SvxBoxItem * pBox = (n == nBoxes) ? nullptr :
2565 &rTabBoxes[n]->GetFrameFormat()->GetBox();
2566 if( !pLastBox )
2567 pLastBox = pBox;
2568 else if( !pBox || *pLastBox != *pBox )
2569 {
2570 // This cell has different borders than the previous cell,
2571 // so output the borders for the preceding cell range.
2572 m_rWW8Export.Out_CellRangeBorders(pLastBox, nSeqStart, n);
2573
2574 // The last column is used as the row default for margins, so we can ignore these matching ones
2575 if ( n == nBoxes )
2576 break;
2577
2578 // Output cell margins.
2579 // One CSSA can define up to all four margins if they are the same size value.
2580 sal_uInt16 nMargin[4];
2581 sal_uInt8 nSideBits[4] = {0, 0, 0, 0}; // 0001:top, 0010:left, 0100:bottom, 1000:right
2582 for ( int i = 0; i < 4; ++i ) // sides: top, left, bottom, right
2583 {
2584 nMargin[i] = std::min(sal_uInt16(31680), pLastBox->GetDistance( aBorders[i] ));
2585 if ( nMargin[i] == nDefaultMargin[i] )
2586 continue;
2587
2588 // join a previous side's definition if it shares the same value
2589 for ( int p = 0; p < 4; ++p )
2590 {
2591 if ( nMargin[i] == nMargin[p] )
2592 {
2593 nSideBits[p] |= 1 << i;
2594 break;
2595 }
2596 }
2597 }
2598
2599 // write out the cell margins definitions that were used
2600 for ( int i = 0; i < 4; ++i )
2601 {
2602 if ( nSideBits[i] )
2603 {
2604 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::TCellPadding::val );
2605 m_rWW8Export.pO->push_back( sal_uInt8(6) ); // 6 bytes
2606 m_rWW8Export.pO->push_back( sal_uInt8(nSeqStart) ); // first cell: apply margin
2607 m_rWW8Export.pO->push_back( sal_uInt8(n) ); // end cell: do not apply margin
2608 m_rWW8Export.pO->push_back( sal_uInt8(nSideBits[i]) );
2609 m_rWW8Export.pO->push_back( sal_uInt8(3) ); // FtsDxa: size in twips
2610 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nMargin[i] );
2611 }
2612 }
2613
2614 nSeqStart = n;
2615 pLastBox = pBox;
2616 }
2617 }
2618}
2619
2620void WW8AttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2621{
2622 const SwTable * pTab = pTableTextNodeInfoInner->getTable();
2623 const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2624 const SwTableLine * pTabLine = pTabBox->GetUpper();
2625 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2626
2627 sal_uInt8 nBoxes = rTabBoxes.size();
2628 m_rWW8Export.InsUInt16( NS_sprm::TDefTableShd80::val );
2629 m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(nBoxes * 2) ); // Len
2630
2631 Color aRowColor = COL_AUTO;
2632 const SvxBrushItem *pTableColorProp = pTab->GetFrameFormat()->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2633 if ( pTableColorProp )
2634 aRowColor = pTableColorProp->GetColor();
2635
2636 const SvxBrushItem *pRowColorProp = pTabLine->GetFrameFormat()->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2637 if ( pRowColorProp && pRowColorProp->GetColor() != COL_AUTO )
2638 aRowColor = pRowColorProp->GetColor();
2639
2640 for ( sal_uInt8 n = 0; n < nBoxes; n++ )
2641 {
2642 const SwTableBox * pBox1 = rTabBoxes[n];
2643 const SwFrameFormat * pFrameFormat = pBox1->GetFrameFormat();
2644 Color aColor = aRowColor;
2645
2646 const SvxBrushItem *pCellColorProp = pFrameFormat->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2647 if ( pCellColorProp && pCellColorProp->GetColor() != COL_AUTO )
2648 aColor = pCellColorProp->GetColor();
2649
2650 WW8_SHD aShd;
2651 WW8Export::TransBrush( aColor, aShd );
2652 m_rWW8Export.InsUInt16( aShd.GetValue() );
2653 }
2654
2655/*sprmTDefTableShdRaw:
2656 * A DefTableShdOperand value that specifies the ... shading for cells 1 up to 22 in the row,
2657 * ... Cells 23 to 44 are shaded by sprmTDefTableShdRaw2nd,
2658 * and cells 45 to 63 are shaded by sprmTDefTableShdRaw3rd.
2659 */
2660 sal_uInt32 const aSprmIds[] { NS_sprm::TDefTableShd::val,
2661 NS_sprm::TDefTableShdRaw::val,
2662 NS_sprm::TDefTableShdRaw::val,
2663 NS_sprm::TDefTableShd2nd::val,
2664 NS_sprm::TDefTableShdRaw2nd::val,
2665 NS_sprm::TDefTableShd3rd::val,
2666 NS_sprm::TDefTableShdRaw3rd::val };
2667 for (sal_uInt32 m : aSprmIds)
2668 {
2669 sal_uInt8 nStart = 0;
2670 sal_uInt8 nStop = rTabBoxes.size();
2671 switch ( m )
2672 {
2673 case NS_sprm::TDefTableShd::val:
2674 case NS_sprm::TDefTableShdRaw::val:
2675 if ( nStop > 21 )
2676 nStop = 22;
2677 break;
2678 case NS_sprm::TDefTableShd2nd::val:
2679 case NS_sprm::TDefTableShdRaw2nd::val:
2680 nStart = 22;
2681 if ( nStop > 43 )
2682 nStop = 44;
2683 break;
2684 case NS_sprm::TDefTableShd3rd::val:
2685 case NS_sprm::TDefTableShdRaw3rd::val:
2686 nStart = 44;
2687 if ( nStop > 62 )
2688 nStop = 63;
2689 break;
2690 }
2691 if ( nStart >= nStop )
2692 break;
2693
2694 m_rWW8Export.InsUInt16( m );
2695 m_rWW8Export.pO->push_back( static_cast<sal_uInt8>((nStop-nStart) * 10) );
2696
2697 for ( sal_uInt8 n = nStart; n < nStop; n++ )
2698 {
2699 const SwTableBox * pBox1 = rTabBoxes[n];
2700 const SwFrameFormat * pFrameFormat = pBox1->GetFrameFormat();
2701 Color aColor = aRowColor;
2702
2703 const SvxBrushItem *pCellColorProp = pFrameFormat->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2704 if ( pCellColorProp && pCellColorProp->GetColor() != COL_AUTO )
2705 aColor = pCellColorProp->GetColor();
2706
2707 WW8SHDLong aSHD;
2708 aSHD.setCvFore( 0xFF000000 );
2709
2710 if ( aColor == COL_AUTO )
2711 aSHD.setCvBack( 0xFF000000 );
2712 else
2713 aSHD.setCvBack( wwUtility::RGBToBGR( aColor ) );
2714
2715 aSHD.Write( m_rWW8Export );
2716 }
2717 }
2718}
2719
2720void WW8Export::SectionBreaksAndFrames( const SwTextNode& rNode )
2721{
2722 // output page/section breaks
2723 OutputSectionBreaks( rNode.GetpSwAttrSet(), rNode );
2724}
2725
2726namespace {
2727
2728class TrackContentToExport
2729{
2730private:
2731 SwPaM *m_pCurPam;
2732 sal_uLong m_nStart, m_nEnd;
2733public:
2734 TrackContentToExport(SwPaM *pCurPam, sal_uLong nCurStart, sal_uLong nCurEnd)
2735 : m_pCurPam(pCurPam)
2736 , m_nStart(nCurStart)
2737 , m_nEnd(nCurEnd)
2738 {
2739 }
2740
2741 bool contentRemainsToExport(ww8::WW8TableInfo *pTableInfo)
2742 {
2743 bool bSimpleContentRemains = m_pCurPam->GetPoint()->nNode < m_pCurPam->GetMark()->nNode ||
2744 (m_pCurPam->GetPoint()->nNode == m_pCurPam->GetMark()->nNode &&
2745 m_pCurPam->GetPoint()->nContent.GetIndex() <= m_pCurPam->GetMark()->nContent.GetIndex());
2746 if (bSimpleContentRemains)
2747 return true;
2748
2749 if (!pTableInfo)
2750 return false;
2751
2752 //An old-school table where one cell may points back to a previous node as the next cell
2753 //so if this node is the last node in the range, we may need to jump back to a previously
2754 //skipped cell to output it in a sane sequence. See ooo47778-3.sxw for one of these
2755 //horrors. So if we are at the end of the selection, but this end point is a table
2756 //cell whose next cell is in the selection allow jumping back to it
2757 const SwNode* pCurrentNode = &m_pCurPam->GetPoint()->nNode.GetNode();
2758 const SwNode* pNextNode = pTableInfo->getNextNode(pCurrentNode);
2759
2760 if (pNextNode && pCurrentNode != pNextNode)
2761 {
2762 return pNextNode->GetIndex() >= m_nStart &&
2763 pNextNode->GetIndex() < m_nEnd;
2764 }
2765
2766 return false;
2767 }
2768};
2769
2770}
2771
2772void MSWordExportBase::WriteText()
2773{
2774 TrackContentToExport aContentTracking(m_pCurPam.get(), m_nCurStart, m_nCurEnd);
2775 while (aContentTracking.contentRemainsToExport(m_pTableInfo.get()))
2776 {
2777 SwNode& rNd = m_pCurPam->GetNode();
2778
2779 // no section breaks exported for Endnotes
2780 if ( rNd.IsTextNode() && m_nTextTyp != TXT_EDN && m_nTextTyp != TXT_FTN )
2781 {
2782 SwSoftPageBreakList breakList;
2783 // if paragraph need to be split than handle section break somewhere
2784 // else.
2785 if( !NeedTextNodeSplit( *rNd.GetTextNode(), breakList) )
2786 SectionBreaksAndFrames( *rNd.GetTextNode() );
2787 }
2788
2789
2790 // output the various types of nodes
2791 if ( rNd.IsContentNode() )
2792 {
2793 SwContentNode* pCNd = static_cast<SwContentNode*>(&rNd);
2794
2795 const SwPageDesc* pTemp = rNd.FindPageDesc();
2796 if ( pTemp )
2797 m_pCurrentPageDesc = pTemp;
2798
2799 m_pCurPam->GetPoint()->nContent.Assign( pCNd, 0 );
2800 OutputContentNode( *pCNd );
2801 }
2802 else if ( rNd.IsTableNode() )
2803 {
2804 m_pTableInfo->processSwTable( &rNd.GetTableNode()->GetTable() );
2805 }
2806 else if ( rNd.IsSectionNode() && TXT_MAINTEXT == m_nTextTyp )
2807 OutputSectionNode( *rNd.GetSectionNode() );
2808 else if ( TXT_MAINTEXT == m_nTextTyp && rNd.IsEndNode() &&
2809 rNd.StartOfSectionNode()->IsSectionNode() )
2810 {
2811 const SwSection& rSect = rNd.StartOfSectionNode()->GetSectionNode()
2812 ->GetSection();
2813 if ( m_bStartTOX && SectionType::ToxContent == rSect.GetType() )
2814 m_bStartTOX = false;
2815
2816 SwNodeIndex aIdx( rNd, 1 );
2817 if ( aIdx.GetNode().IsEndNode() && aIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
2818 ;
2819 else if ( aIdx.GetNode().IsSectionNode() )
2820 ;
2821 else if ( !IsInTable() ) //No sections in table
2822 {
2823 //#120140# Do not need to insert a page/section break after a section end. Check this case first
2824 bool bNeedExportBreakHere = true;
2825 if ( rSect.GetType() == SectionType::ToxContent || rSect.GetType() == SectionType::ToxHeader )
2826 bNeedExportBreakHere = false;
2827 else if ( aIdx.GetNode().IsTextNode() )
2828 {
2829 SwTextNode *pTempNext = aIdx.GetNode().GetTextNode();
2830 if ( pTempNext )
2831 {
2832 const SfxPoolItem * pTempItem = nullptr;
2833 if (pTempNext->GetpSwAttrSet() && SfxItemState::SET == pTempNext->GetpSwAttrSet()->GetItemState(RES_PAGEDESC, false, &pTempItem)
2834 && pTempItem && static_cast<const SwFormatPageDesc*>(pTempItem)->GetRegisteredIn())
2835 {
2836 //Next node has a new page style which means this node is a section end. Do not insert another page/section break here
2837 bNeedExportBreakHere = false;
2838 }
2839 }
2840 }
2841 else
2842 {
2843 /* Do not export Section Break in case DOCX containing MultiColumn and
2844 * aIdx.GetNode().IsTextNode() is False i.e. Text node is NULL.
2845 */
2846 const SwFrameFormat* pPgFormat = rSect.GetFormat();
2847 const SwFormatCol& rCol = pPgFormat->GetCol();
2848 sal_uInt16 nColumnCount = rCol.GetNumCols();
2849 const SwFormatNoBalancedColumns& rNoBalanced = pPgFormat->GetBalancedColumns();
2850 // Prevent the additional section break only for non-balanced columns.
2851 if (nColumnCount > 1 && rNoBalanced.GetValue())
2852 {
2853 bNeedExportBreakHere = false;
2854 }
2855 // No need to create a "fake" section if this is the end of the document,
2856 // except to emulate balanced columns.
2857 else if ( nColumnCount < 2 && aIdx == m_rDoc.GetNodes().GetEndOfContent() )
2858 bNeedExportBreakHere = false;
2859 }
2860
2861 if (bNeedExportBreakHere) //#120140# End of check
2862 {
2863 ReplaceCr( char(0xc) ); // indicator for Page/Section-Break
2864
2865 const SwSectionFormat* pParentFormat = rSect.GetFormat()->GetParent();
2866 if ( !pParentFormat )
2867 pParentFormat = reinterpret_cast<SwSectionFormat*>(sal_IntPtr(-1));
2868
2869 sal_uLong nRstLnNum;
2870 if ( aIdx.GetNode().IsContentNode() )
2871 nRstLnNum = static_cast<SwContentNode&>(aIdx.GetNode()).GetSwAttrSet().
2872 GetLineNumber().GetStartValue();
2873 else
2874 nRstLnNum = 0;
2875
2876 AppendSection( m_pCurrentPageDesc, pParentFormat, nRstLnNum );
2877 }
2878 else
2879 {
2880 OutputEndNode( *rNd.GetEndNode() );
2881 }
2882 }
2883 }
2884 else if ( rNd.IsStartNode() )
2885 {
2886 OutputStartNode( *rNd.GetStartNode() );
2887 }
2888 else if ( rNd.IsEndNode() )
2889 {
2890 OutputEndNode( *rNd.GetEndNode() );
2891 }
2892
2893 if ( &rNd == &rNd.GetNodes().GetEndOfContent() )
2894 break;
2895
2896 const SwNode * pCurrentNode = &m_pCurPam->GetPoint()->nNode.GetNode();
2897 const SwNode * pNextNode = m_pTableInfo->getNextNode(pCurrentNode);
2898
2899 if (pCurrentNode == pNextNode)
2900 {
2901 SAL_WARN("sw.ww8", "loop in TableInfo")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "loop in TableInfo") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2901" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "loop in TableInfo"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"loop in TableInfo"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2901" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "loop in TableInfo") == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2901" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "loop in TableInfo"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"loop in TableInfo"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2901" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2902 pNextNode = nullptr;
2903 }
2904
2905 if (pNextNode != nullptr)
2906 m_pCurPam->GetPoint()->nNode.Assign(*pNextNode);
2907 else
2908 ++m_pCurPam->GetPoint()->nNode;
2909
2910 sal_uLong nPos = m_pCurPam->GetPoint()->nNode.GetIndex();
2911 ::SetProgressState( nPos, m_pCurPam->GetDoc().GetDocShell() );
2912 }
2913
2914 SAL_INFO( "sw.ww8.level2", "</WriteText>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "</WriteText>")
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2914" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</WriteText>"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"</WriteText>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2914" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "</WriteText>") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2914" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</WriteText>"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"</WriteText>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2914" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2915}
2916
2917void WW8Export::WriteMainText()
2918{
2919 SAL_INFO( "sw.ww8.level2", "<WriteMainText>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "<WriteMainText>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2919" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<WriteMainText>"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"<WriteMainText>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2919" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "<WriteMainText>") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2919" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<WriteMainText>"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"<WriteMainText>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2919" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2920
2921 pFib->m_fcMin = Strm().Tell();
2922
2923 m_pCurPam->GetPoint()->nNode = m_rDoc.GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
2924
2925 WriteText();
2926
2927 if( 0 == Strm().Tell() - pFib->m_fcMin ) // no text ?
2928 WriteCR(); // then CR at the end ( otherwise WW will complain )
2929
2930 pFib->m_ccpText = Fc2Cp( Strm().Tell() );
2931 m_pFieldMain->Finish( pFib->m_ccpText, 0 );
2932
2933 // ccpText includes Footnote and KF-text
2934 // therefore pFib->ccpText may get updated as well
2935 // save the StyleId of the last paragraph. Because WW97 take the style
2936 // from the last CR, that will be written after footer/Header/footnotes/
2937 // annotation etc.
2938 const SwTextNode* pLastNd = m_pCurPam->GetMark()->nNode.GetNode().GetTextNode();
2939 if( pLastNd )
2940 m_nLastFormatId = GetId( static_cast<SwTextFormatColl&>(pLastNd->GetAnyFormatColl()) );
2941
2942 SAL_INFO( "sw.ww8.level2", "</WriteMainText>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8.level2")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "</WriteMainText>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2942" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</WriteMainText>"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"</WriteMainText>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2942" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "</WriteMainText>") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2942" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</WriteMainText>"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"</WriteMainText>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8.level2"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "2942" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2943}
2944
2945bool MSWordExportBase::IsInTable() const
2946{
2947 bool bResult = false;
2948
2949 if (m_pCurPam != nullptr)
2950 {
2951 SwNode& rNode = m_pCurPam->GetNode();
2952
2953 if (m_pTableInfo)
2954 {
2955 ww8::WW8TableNodeInfo::Pointer_t pTableNodeInfo = m_pTableInfo->getTableNodeInfo(&rNode);
2956
2957 if (pTableNodeInfo && pTableNodeInfo->getDepth() > 0)
2958 {
2959 bResult = true;
2960 }
2961 }
2962 }
2963
2964 return bResult;
2965}
2966
2967typedef ww8::WW8Sttb< ww8::WW8Struct > WW8SttbAssoc;
2968
2969void WW8Export::WriteFkpPlcUsw()
2970{
2971 // Graphics in the data stream
2972 m_pGrf->Write(); // Graphics
2973
2974 // output into WordDocument stream
2975 m_pChpPlc->WriteFkps(); // Fkp.Chpx
2976 m_pPapPlc->WriteFkps(); // Fkp.Papx
2977 pSepx->WriteSepx( Strm() ); // Sepx
2978
2979 // output into Table stream
2980 m_pStyles->OutputStylesTable(); // for WW8 StyleTab
2981 pFootnote->WritePlc( *this ); // Footnote-Ref & Text Plc
2982 pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
2983 m_pTextBxs->WritePlc( *this ); // Textbox Text Plc
2984 m_pHFTextBxs->WritePlc( *this ); // Head/Foot-Textbox Text Plc
2985 m_pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
2986
2987 pSepx->WritePlcSed( *this ); // Slcx.PlcSed
2988 pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
2989
2990 m_pChpPlc->WritePlc(); // Plcx.Chpx
2991 m_pPapPlc->WritePlc(); // Plcx.Papx
2992
2993 if( m_pRedlAuthors )
2994 m_pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2995 m_pFieldMain->Write( *this ); // Fields ( Main Text )
2996 m_pFieldHdFt->Write( *this ); // Fields ( Header/Footer )
2997 m_pFieldFootnote->Write( *this ); // Fields ( FootNotes )
2998 m_pFieldEdn->Write( *this ); // Fields ( EndNotes )
2999 m_pFieldAtn->Write( *this ); // Fields ( Annotations )
3000 m_pFieldTextBxs->Write( *this ); // Fields ( Textboxes )
3001 m_pFieldHFTextBxs->Write( *this ); // Fields ( Head/Foot-Textboxes )
3002
3003 if (m_pEscher || m_rDoc.ContainsMSVBasic())
3004 {
3005 /*
3006 Every time MS 2000 creates an escher stream there is always
3007 an ObjectPool dir (even if empty). It turns out that if a copy of
3008 MS 2000 is used to open a document that contains escher graphics
3009 exported from StarOffice without this empty dir then *if* that
3010 copy of MS Office has never been used to open a MSOffice document
3011 that has escher graphics (and an ObjectPool dir of course) and
3012 that copy of office has not been used to draw escher graphics then
3013 our exported graphics do not appear. Once you do open a ms
3014 document with escher graphics or draw an escher graphic with that
3015 copy of word, then all documents from staroffice that contain
3016 escher work from then on. Tricky to track down, some sort of late
3017 binding trickery in MS where solely for first time initialization
3018 the existence of an ObjectPool dir is necessary for triggering
3019 some magic.
3020 */
3021 // avoid memory leak #i120098#, the unnamed obj will be released in destructor.
3022 xEscherStg = GetWriter().GetStorage().OpenSotStorage(SL::aObjectPool);
3023 }
3024
3025 // dggInfo - escher stream
3026 WriteEscher();
3027
3028 m_pSdrObjs->WritePlc( *this );
3029 m_pHFSdrObjs->WritePlc( *this );
3030 // spamom - office drawing table
3031 // spahdr - header office drawing table
3032
3033 m_pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
3034 // plcfBkmkf/plcfBkmkl
3035 m_pFactoids->Write(*this);
3036
3037 WriteNumbering();
3038
3039 RestoreMacroCmds();
3040
3041 m_pMagicTable->Write( *this );
3042
3043 m_pPiece->WritePc( *this ); // Piece-Table
3044 m_aFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
3045
3046 //Convert OOo asian typography into MS typography structure
3047 ExportDopTypography(pDop->doptypography);
3048
3049 WriteDop( *this ); // Document-Properties
3050
3051 // Write SttbfAssoc
3052 WW8SttbAssoc * pSttbfAssoc = dynamic_cast<WW8SttbAssoc *>
3053 (m_rDoc.getIDocumentExternalData().getExternalData(::sw::tExternalDataType::STTBF_ASSOC).get());
3054
3055 if ( pSttbfAssoc ) // #i106057#
3056 {
3057 std::vector<OUString> aStrings(pSttbfAssoc->getStrings());
3058 WriteAsStringTable(aStrings, pFib->m_fcSttbfAssoc,
3059 pFib->m_lcbSttbfAssoc);
3060 }
3061
3062 Strm().Seek( 0 );
3063
3064 // Reclaim stored FIB data from document.
3065 ::ww8::WW8FibData * pFibData = dynamic_cast<ww8::WW8FibData *>
3066 (m_rDoc.getIDocumentExternalData().getExternalData(::sw::tExternalDataType::FIB).get());
3067
3068 if ( pFibData )
3069 {
3070 pFib->m_fReadOnlyRecommended =
3071 pFibData->getReadOnlyRecommended();
3072 pFib->m_fWriteReservation =
3073 pFibData->getWriteReservation();
3074 }
3075
3076 pFib->Write( Strm() ); // FIB
3077}
3078
3079void WW8Export::StoreDoc1()
3080{
3081 bool bNeedsFinalPara = false;
3082 // Start of Text ( overwrite )
3083 SwWW8Writer::FillUntil( Strm(), pFib->m_fcMin );
3084
3085 WriteMainText(); // main text
3086 sal_uInt8 nSprmsLen;
3087 sal_uInt8 *pLastSprms = m_pPapPlc->CopyLastSprms(nSprmsLen);
3088
3089 bNeedsFinalPara |= pFootnote->WriteText( *this ); // Footnote-Text
3090 bNeedsFinalPara |= pSepx->WriteKFText( *this ); // K/F-Text
3091 bNeedsFinalPara |= m_pAtn->WriteText( *this ); // Annotation-Text
3092 bNeedsFinalPara |= pEdn->WriteText( *this ); // EndNote-Text
3093
3094 // create the escher streams
3095 CreateEscher();
3096
3097 bNeedsFinalPara |= m_pTextBxs->WriteText( *this ); //Textbox Text Plc
3098 bNeedsFinalPara |= m_pHFTextBxs->WriteText( *this );//Head/Foot-Textbox Text Plc
3099
3100 if (bNeedsFinalPara)
3101 {
3102 WriteCR();
3103 m_pPapPlc->AppendFkpEntry(Strm().Tell(), nSprmsLen, pLastSprms);
3104 }
3105 delete[] pLastSprms;
3106
3107 pSepx->Finish( Fc2Cp( Strm().Tell() ));// Text + Footnote + HdFt as section end
3108 m_pMagicTable->Finish( Fc2Cp( Strm().Tell() ),0);
3109
3110 pFib->m_fcMac = Strm().Tell(); // End of all texts
3111
3112 WriteFkpPlcUsw(); // FKP, PLC, ...
3113}
3114
3115void MSWordExportBase::AddLinkTarget(const OUString& rURL)
3116{
3117 if( rURL.isEmpty() || rURL[0] != '#' )
3118 return;
3119
3120 OUString aURL( BookmarkToWriter( rURL.copy( 1 ) ) );
3121 sal_Int32 nPos = aURL.lastIndexOf( cMarkSeparator );
3122
3123 if( nPos < 2 )
3124 return;
3125
3126 OUString sCmp = aURL.copy(nPos+1).replaceAll(" ", "");
3127 if( sCmp.isEmpty() )
3128 return;
3129
3130 sCmp = sCmp.toAsciiLowerCase();
3131 sal_uLong nIdx = 0;
3132 bool noBookmark = false;
3133
3134 if( sCmp == "outline" )
3135 {
3136 SwPosition aPos(*m_pCurPam->GetPoint());
3137 OUString aName(BookmarkToWriter(aURL.copy(0, nPos)));
3138 // If we can find the outline this bookmark refers to
3139 // save the name of the bookmark and the
3140 // node index number of where it points to
3141 if( m_rDoc.GotoOutline( aPos, aName ) )
3142 {
3143 nIdx = aPos.nNode.GetIndex();
3144 noBookmark = true;
3145 }
3146 }
3147 else if( sCmp == "graphic" )
3148 {
3149 SwNodeIndex* pIdx;
3150 OUString aName(BookmarkToWriter(aURL.copy(0, nPos)));
3151 const SwFlyFrameFormat* pFormat = m_rDoc.FindFlyByName(aName, SwNodeType::Grf);
3152 if (pFormat && nullptr != (pIdx = const_cast<SwNodeIndex*>(pFormat->GetContent().GetContentIdx())))
3153 {
3154 nIdx = pIdx->GetNext()->GetIndex();
3155 noBookmark = true;
3156 }
3157 }
3158 else if( sCmp == "frame" )
3159 {
3160 SwNodeIndex* pIdx;
3161 OUString aName(BookmarkToWriter(aURL.copy(0, nPos)));
3162 const SwFlyFrameFormat* pFormat = m_rDoc.FindFlyByName(aName, SwNodeType::Text);
3163 if (pFormat && nullptr != (pIdx = const_cast<SwNodeIndex*>(pFormat->GetContent().GetContentIdx())))
3164 {
3165 nIdx = pIdx->GetIndex() + 1;
3166 noBookmark = true;
3167 }
3168 }
3169 else if( sCmp == "ole" )
3170 {
3171 SwNodeIndex* pIdx;
3172 OUString aName(BookmarkToWriter(aURL.copy(0, nPos)));
3173 const SwFlyFrameFormat* pFormat = m_rDoc.FindFlyByName(aName, SwNodeType::Ole);
3174 if (pFormat && nullptr != (pIdx = const_cast<SwNodeIndex*>(pFormat->GetContent().GetContentIdx())))
3175 {
3176 nIdx = pIdx->GetNext()->GetIndex();
3177 noBookmark = true;
3178 }
3179 }
3180 else if( sCmp == "region" )
3181 {
3182 SwNodeIndex* pIdx;
3183 OUString aName(BookmarkToWriter(aURL.copy(0, nPos)));
3184 for (const SwSectionFormat* pFormat : m_rDoc.GetSections())
3185 {
3186 if (aName == pFormat->GetSection()->GetSectionName()
3187 && nullptr != (pIdx = const_cast<SwNodeIndex*>(pFormat->GetContent().GetContentIdx())))
3188 {
3189 nIdx = pIdx->GetIndex() + 1;
3190 noBookmark = true;
3191 break;
3192 }
3193 }
3194 }
3195 else if( sCmp == "table" )
3196 {
3197 OUString aName(BookmarkToWriter(aURL.copy(0, nPos)));
3198 const SwTable* pTable = SwTable::FindTable(m_rDoc.FindTableFormatByName(aName));
3199 if (pTable)
3200 {
3201 SwTableNode* pTableNode = const_cast<SwTableNode*>(pTable->GetTabSortBoxes()[1]->GetSttNd()->FindTableNode());
3202 if (pTableNode)
3203 {
3204 nIdx = pTableNode->GetIndex() + 2;
3205 noBookmark = true;
3206 }
3207 }
3208 }
3209 if (noBookmark)
3210 {
3211 aBookmarkPair aImplicitBookmark;
3212 aImplicitBookmark.first = aURL;
3213 aImplicitBookmark.second = nIdx;
3214 m_aImplicitBookmarks.push_back(aImplicitBookmark);
3215 }
3216}
3217
3218void MSWordExportBase::CollectOutlineBookmarks(const SwDoc &rDoc)
3219{
3220 for (const SfxPoolItem* pItem : rDoc.GetAttrPool().GetItemSurrogates(RES_TXTATR_INETFMT))
3221 {
3222 auto pINetFormat = dynamic_cast<const SwFormatINetFormat*>(pItem);
3223 if (!pINetFormat)
3224 continue;
3225
3226 const SwTextINetFormat* pTextAttr = pINetFormat->GetTextINetFormat();
3227 if (!pTextAttr)
3228 continue;
3229
3230 const SwTextNode* pTextNd = pTextAttr->GetpTextNode();
3231 if (!pTextNd)
3232 continue;
3233
3234 if (!pTextNd->GetNodes().IsDocNodes())
3235 continue;
3236
3237 AddLinkTarget( pINetFormat->GetValue() );
3238 }
3239
3240 for (const SfxPoolItem* pItem : rDoc.GetAttrPool().GetItemSurrogates(RES_URL))
3241 {
3242 auto pURL = dynamic_cast<const SwFormatURL*>(pItem);
3243 if (!pURL)
3244 continue;
3245
3246 AddLinkTarget(pURL->GetURL());
3247 const ImageMap *pIMap = pURL->GetMap();
3248 if (!pIMap)
3249 continue;
3250
3251 for (size_t i=0; i < pIMap->GetIMapObjectCount(); ++i)
3252 {
3253 const IMapObject* pObj = pIMap->GetIMapObject(i);
3254 if (!pObj)
3255 continue;
3256 AddLinkTarget( pObj->GetURL() );
3257 }
3258 }
3259}
3260
3261namespace
3262{
3263 const sal_uLong WW_BLOCKSIZE = 0x200;
3264
3265 ErrCode EncryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
3266 {
3267 sal_uLong nLen = rIn.TellEnd();
3268 rIn.Seek(0);
3269
3270 sal_uInt8 in[WW_BLOCKSIZE];
3271 for (std::size_t nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
3272 {
3273 std::size_t nBS = std::min(nLen - nI, WW_BLOCKSIZE);
3274 nBS = rIn.ReadBytes(in, nBS);
3275 if (!rCtx.InitCipher(nBlock)) {
3276 return ERRCODE_IO_NOTSUPPORTEDErrCode( ErrCodeArea::Io, ErrCodeClass::NotSupported, 12 );
3277 }
3278 rCtx.Encode(in, nBS, in, nBS);
3279 rOut.WriteBytes(in, nBS);
3280 }
3281 return ERRCODE_NONEErrCode(0);
3282 }
3283}
3284
3285ErrCode MSWordExportBase::ExportDocument( bool bWriteAll )
3286{
3287 m_nCharFormatStart = DEFAULT_STYLES_COUNT16;
3288 m_nFormatCollStart = m_nCharFormatStart + m_rDoc.GetCharFormats()->size() - 1;
3289
3290 m_bStyDef = m_bBreakBefore = m_bOutKF =
3291 m_bOutFlyFrameAttrs = m_bOutPageDescs = m_bOutTable = m_bOutFirstPage =
3292 m_bOutGrf = m_bInWriteEscher = m_bStartTOX =
3293 m_bInWriteTOX = false;
3294
3295 m_bFootnoteAtTextEnd = m_bEndAtTextEnd = true;
3296
3297 m_pParentFrame = nullptr;
3298 m_pFlyOffset = nullptr;
3299 m_eNewAnchorType = RndStdIds::FLY_AT_PAGE;
3300 m_nTextTyp = TXT_MAINTEXT;
3301 m_nStyleBeforeFly = m_nLastFormatId = 0;
3302 m_pStyAttr = nullptr;
3303 m_pCurrentStyle = nullptr;
3304 m_pOutFormatNode = nullptr;
3305 m_pEscher = nullptr;
3306 m_pRedlAuthors = nullptr;
3307 m_aTOXArr.clear();
3308
3309 if ( !m_pOLEExp )
3310 {
3311 sal_uInt32 nSvxMSDffOLEConvFlags = 0;
3312 const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
3313 if ( rOpt.IsMath2MathType() )
3314 nSvxMSDffOLEConvFlags |= OLE_STARMATH_2_MATHTYPE0x0001;
3315 if ( rOpt.IsWriter2WinWord() )
3316 nSvxMSDffOLEConvFlags |= OLE_STARWRITER_2_WINWORD0x0002;
3317 if ( rOpt.IsCalc2Excel() )
3318 nSvxMSDffOLEConvFlags |= OLE_STARCALC_2_EXCEL0x0004;
3319 if ( rOpt.IsImpress2PowerPoint() )
3320 nSvxMSDffOLEConvFlags |= OLE_STARIMPRESS_2_POWERPOINT0x0008;
3321
3322 m_pOLEExp.reset(new SvxMSExportOLEObjects( nSvxMSDffOLEConvFlags ));
3323 }
3324
3325 if ( !m_pOCXExp && m_rDoc.GetDocShell() )
3326 m_pOCXExp.reset(new SwMSConvertControls(m_rDoc.GetDocShell(), m_pCurPam.get()));
3327
3328 // #i81405# - Collect anchored objects before changing the redline mode.
3329 m_aFrames = GetFrames( m_rDoc, bWriteAll? nullptr : m_pOrigPam );
3330
3331 m_nOrigRedlineFlags = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags();
3332
3333 SwRootFrame const*const pLayout(m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout());
3334 m_bOrigShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
3335
3336 if ( !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() )
3337 {
3338 //restored to original state by SwWriter::Write
3339 m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags(m_nOrigRedlineFlags |
3340 RedlineFlags::ShowDelete |
3341 RedlineFlags::ShowInsert);
3342 }
3343
3344 // fix the SwPositions in m_aFrames after SetRedlineFlags
3345 UpdateFramePositions(m_aFrames);
3346
3347 m_aFontHelper.InitFontTable(m_rDoc);
3348 GatherChapterFields();
3349
3350 CollectOutlineBookmarks(m_rDoc);
3351
3352 // make unique OrdNums (Z-Order) for all drawing-/fly Objects
3353 if ( m_rDoc.getIDocumentDrawModelAccess().GetDrawModel() )
3354 m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->GetPage( 0 )->RecalcObjOrdNums();
3355
3356 ErrCode err = ExportDocument_Impl();
3357
3358 m_aFrames.clear();
3359
3360 // park m_pCurPam in a "safe place" now that document is fully exported
3361 // before toggling redline mode to avoid ~SwIndexReg assert e.g. export
3362 // ooo103014-1.odt to .doc
3363 // park m_pOrigPam as well, as needed for exporting abi9915-1.odt to doc
3364 m_pOrigPam->DeleteMark();
3365 *m_pOrigPam->GetPoint() = SwPosition(m_rDoc.GetNodes().GetEndOfContent());
3366 static_cast<SwPaM&>(*m_pCurPam) = *m_pOrigPam;
3367
3368 m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags(m_nOrigRedlineFlags);
3369
3370 return err;
3371}
3372
3373bool SwWW8Writer::InitStd97CodecUpdateMedium( ::msfilter::MSCodec_Std97& rCodec )
3374{
3375 uno::Sequence< beans::NamedValue > aEncryptionData;
3376
3377 if ( mpMedium )
3378 {
3379 const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mpMedium->GetItemSet(), SID_ENCRYPTIONDATA(5000 + 1722), false);
3380 if ( pEncryptionDataItem && ( pEncryptionDataItem->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
3381 {
3382 OSL_ENSURE( false, "Unexpected EncryptionData!" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "3382" ": "), "%s", "Unexpected EncryptionData!"); } } while
(false)
;
3383 aEncryptionData.realloc( 0 );
3384 }
3385
3386 if ( !aEncryptionData.hasElements() )
3387 {
3388 // try to generate the encryption data based on password
3389 const SfxStringItem* pPasswordItem = SfxItemSet::GetItem<SfxStringItem>(mpMedium->GetItemSet(), SID_PASSWORD(((((10000 + 1499) + 1) + 499) + 1) + 36), false);
3390 if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() && pPasswordItem->GetValue().getLength() <= 15 )
3391 {
3392 // Generate random number with a seed of time as salt.
3393 rtlRandomPool aRandomPool = rtl_random_createPool ();
3394 sal_uInt8 pDocId[ 16 ];
3395 rtl_random_getBytes( aRandomPool, pDocId, 16 );
3396
3397 rtl_random_destroyPool( aRandomPool );
3398
3399 sal_uInt16 aPassword[16] = {};
3400
3401 const OUString& sPassword(pPasswordItem->GetValue());
3402 for ( sal_Int32 nChar = 0; nChar < sPassword.getLength(); ++nChar )
3403 aPassword[nChar] = sPassword[nChar];
3404
3405 rCodec.InitKey( aPassword, pDocId );
3406 aEncryptionData = rCodec.GetEncryptionData();
3407
3408 mpMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA(5000 + 1722), uno::makeAny( aEncryptionData ) ) );
3409 }
3410 }
3411
3412 if ( aEncryptionData.hasElements() )
3413 mpMedium->GetItemSet()->ClearItem( SID_PASSWORD(((((10000 + 1499) + 1) + 499) + 1) + 36) );
3414 }
3415
3416 // nonempty encryption data means here that the codec was successfully initialized
3417 return aEncryptionData.hasElements();
3418}
3419
3420ErrCode WW8Export::ExportDocument_Impl()
3421{
3422 PrepareStorage();
3423
3424 pFib.reset(new WW8Fib(8, m_bDot));
3425
3426 tools::SvRef<SotStorageStream> xWwStrm( GetWriter().GetStorage().OpenSotStream( m_aMainStg ) );
3427 tools::SvRef<SotStorageStream> xTableStrm( xWwStrm ), xDataStrm( xWwStrm );
3428 xWwStrm->SetBufferSize( 32768 );
3429
3430 pFib->m_fWhichTableStm = true;
3431 xTableStrm = GetWriter().GetStorage().OpenSotStream(SL::a1Table, StreamMode::STD_WRITE);
3432 xDataStrm = GetWriter().GetStorage().OpenSotStream(SL::aData, StreamMode::STD_WRITE);
3433
3434 xDataStrm->SetBufferSize( 32768 ); // for graphics
3435 xTableStrm->SetBufferSize( 16384 ); // for the Font-/Style-Table, etc.
3436
3437 xTableStrm->SetEndian( SvStreamEndian::LITTLE );
3438 xDataStrm->SetEndian( SvStreamEndian::LITTLE );
3439
3440 GetWriter().SetStream( xWwStrm.get() );
3441 pTableStrm = xTableStrm.get();
3442 pDataStrm = xDataStrm.get();
3443
3444 Strm().SetEndian( SvStreamEndian::LITTLE );
3445
3446 utl::TempFile aTempMain;
3447 aTempMain.EnableKillingFile();
3448 utl::TempFile aTempTable;
3449 aTempTable.EnableKillingFile();
3450 utl::TempFile aTempData;
3451 aTempData.EnableKillingFile();
3452
3453 msfilter::MSCodec_Std97 aCtx;
3454 bool bEncrypt = GetWriter().InitStd97CodecUpdateMedium(aCtx);
3455 if ( bEncrypt )
3456 {
3457 GetWriter().SetStream(
3458 aTempMain.GetStream( StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE ) );
3459
3460 pTableStrm = aTempTable.GetStream( StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE );
3461
3462 pDataStrm = aTempData.GetStream( StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE );
3463
3464 sal_uInt8 const aRC4EncryptionHeader[ 52 ] = {0};
3465 pTableStrm->WriteBytes(aRC4EncryptionHeader, 52);
3466 }
3467
3468 // Default: "Standard"
3469 pSepx.reset(new WW8_WrPlcSepx( *this )); // Sections/headers/footers
3470
3471 pFootnote.reset(new WW8_WrPlcFootnoteEdn( TXT_FTN )); // Footnotes
3472 pEdn.reset(new WW8_WrPlcFootnoteEdn( TXT_EDN )); // Endnotes
3473 m_pAtn = new WW8_WrPlcAnnotations; // PostIts
3474 m_pFactoids.reset(new WW8_WrtFactoids); // Smart tags.
3475 m_pTextBxs = new WW8_WrPlcTextBoxes( TXT_TXTBOX );
3476 m_pHFTextBxs = new WW8_WrPlcTextBoxes( TXT_HFTXTBOX );
3477
3478 m_pSdrObjs = new MainTextPlcDrawObj; // Draw-/Fly-Objects for main text
3479 m_pHFSdrObjs = new HdFtPlcDrawObj; // Draw-/Fly-Objects for header/footer
3480
3481 m_pBkmks = new WW8_WrtBookmarks; // Bookmarks
3482 GetWriter().CreateBookmarkTable();
3483
3484 m_pPapPlc.reset(new WW8_WrPlcPn( *this, PAP, pFib->m_fcMin ));
3485 m_pChpPlc.reset(new WW8_WrPlcPn( *this, CHP, pFib->m_fcMin ));
3486 pO.reset(new ww::bytes);
3487 m_pStyles.reset(new MSWordStyles( *this ));
3488 m_pFieldMain.reset(new WW8_WrPlcField( 2, TXT_MAINTEXT ));
3489 m_pFieldHdFt.reset(new WW8_WrPlcField( 2, TXT_HDFT ));
3490 m_pFieldFootnote.reset(new WW8_WrPlcField( 2, TXT_FTN ));
3491 m_pFieldEdn.reset(new WW8_WrPlcField( 2, TXT_EDN ));
3492 m_pFieldAtn.reset(new WW8_WrPlcField( 2, TXT_ATN ));
3493 m_pFieldTextBxs.reset(new WW8_WrPlcField( 2, TXT_TXTBOX ));
3494 m_pFieldHFTextBxs.reset(new WW8_WrPlcField( 2, TXT_HFTXTBOX ));
3495
3496 m_pMagicTable.reset(new WW8_WrMagicTable);
3497
3498 m_pGrf.reset(new SwWW8WrGrf( *this ));
3499 m_pPiece = new WW8_WrPct( pFib->m_fcMin );
3500 pDop.reset(new WW8Dop);
3501
3502 pDop->fRevMarking = bool( RedlineFlags::On & m_nOrigRedlineFlags );
3503 SwRootFrame const*const pLayout(m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout());
3504 pDop->fRMView = pLayout == nullptr || !pLayout->IsHideRedlines();
3505 pDop->fRMPrint = pDop->fRMView;
3506
3507 // set AutoHyphenation flag if found in default para style
3508 const SfxPoolItem* pItem;
3509 SwTextFormatColl* pStdTextFormatColl =
3510 m_rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, false);
3511 if (pStdTextFormatColl && SfxItemState::SET == pStdTextFormatColl->GetItemState(
3512 RES_PARATR_HYPHENZONE, false, &pItem))
3513 {
3514 pDop->fAutoHyphen = static_cast<const SvxHyphenZoneItem*>(pItem)->IsHyphen();
3515 }
3516
3517 StoreDoc1();
3518
3519 ErrCode err = ERRCODE_NONEErrCode(0);
3520 if ( bEncrypt )
3521 {
3522 SvStream *pStrmTemp, *pTableStrmTemp, *pDataStrmTemp;
3523 pStrmTemp = xWwStrm.get();
3524 pTableStrmTemp = xTableStrm.get();
3525 pDataStrmTemp = xDataStrm.get();
3526
3527 if ( pDataStrmTemp && pDataStrmTemp != pStrmTemp) {
3528 err = EncryptRC4(aCtx, *pDataStrm, *pDataStrmTemp);
3529 if (err != ERRCODE_NONEErrCode(0)) {
3530 goto done;
3531 }
3532 }
3533
3534 err = EncryptRC4(aCtx, *pTableStrm, *pTableStrmTemp);
3535 if (err != ERRCODE_NONEErrCode(0)) {
3536 goto done;
3537 }
3538
3539 // Write Unencrypted Header 52 bytes to the start of the table stream
3540 // EncryptionVersionInfo (4 bytes): A Version structure where Version.vMajor MUST be 0x0001, and Version.vMinor MUST be 0x0001.
3541 pTableStrmTemp->Seek( 0 );
3542 pTableStrmTemp->WriteUInt32( 0x10001 ); // nEncType
3543
3544 sal_uInt8 pDocId[16];
3545 aCtx.GetDocId( pDocId );
3546
3547 sal_uInt8 pSaltData[16];
3548 sal_uInt8 pSaltDigest[16];
3549 aCtx.GetEncryptKey( pDocId, pSaltData, pSaltDigest );
3550
3551 pTableStrmTemp->WriteBytes(pDocId, 16);
3552 pTableStrmTemp->WriteBytes(pSaltData, 16);
3553 pTableStrmTemp->WriteBytes(pSaltDigest, 16);
3554
3555 err = EncryptRC4(aCtx, GetWriter().Strm(), *pStrmTemp);
3556 if (err != ERRCODE_NONEErrCode(0)) {
3557 goto done;
3558 }
3559
3560 // Write Unencrypted Fib 68 bytes to the start of the workdocument stream
3561 pFib->m_fEncrypted = true; // fEncrypted indicates the document is encrypted.
3562 pFib->m_fObfuscated = false; // Must be 0 for RC4.
3563 pFib->m_nHash = 0x34; // encrypt header bytes count of table stream.
3564 pFib->m_nKey = 0; // lkey2 must be 0 for RC4.
3565
3566 pStrmTemp->Seek( 0 );
3567 pFib->WriteHeader( *pStrmTemp );
3568 done:;
3569 }
3570
3571 m_pGrf.reset();
3572 m_pMagicTable.reset();
3573 m_pFieldFootnote.reset();
3574 m_pFieldTextBxs.reset();
3575 m_pFieldHFTextBxs.reset();
3576 m_pFieldAtn.reset();
3577 m_pFieldEdn.reset();
3578 m_pFieldHdFt.reset();
3579 m_pFieldMain.reset();
3580 m_pStyles.reset();
3581 pO.reset();
3582 m_pChpPlc.reset();
3583 m_pPapPlc.reset();
3584 pSepx.reset();
3585
3586 delete m_pRedlAuthors;
3587 delete m_pSdrObjs;
3588 delete m_pHFSdrObjs;
3589 delete m_pTextBxs;
3590 delete m_pHFTextBxs;
3591 delete m_pAtn;
3592 pEdn.reset();
3593 pFootnote.reset();
3594 delete m_pBkmks;
3595 delete m_pPiece;
3596 pDop.reset();
3597 pFib.reset();
3598 GetWriter().SetStream( nullptr );
3599
3600 xWwStrm->SetBufferSize( 0 );
3601 xTableStrm->SetBufferSize( 0 );
3602 xDataStrm->SetBufferSize( 0 );
3603 if( 0 == pDataStrm->Seek( STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul) ))
3604 {
3605 xDataStrm.clear();
3606 pDataStrm = nullptr;
3607 GetWriter().GetStorage().Remove(SL::aData);
3608 }
3609
3610 return err;
3611}
3612
3613void WW8Export::PrepareStorage()
3614{
3615 static const sal_uInt8 pData[] =
3616 {
3617 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3618 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x09, 0x02, 0x00,
3619 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3620 0x00, 0x00, 0x00, 0x46,
3621
3622 0x18, 0x00, 0x00, 0x00,
3623 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
3624 't', ' ', 'W', 'o', 'r', 'd', '-', 'D',
3625 'o', 'k', 'u', 'm', 'e', 'n', 't', 0x0,
3626
3627 0x0A, 0x00, 0x00, 0x00,
3628 'M', 'S', 'W', 'o', 'r', 'd', 'D', 'o',
3629 'c', 0x0,
3630
3631 0x10, 0x00, 0x00, 0x00,
3632 'W', 'o', 'r', 'd', '.', 'D', 'o', 'c',
3633 'u', 'm', 'e', 'n', 't', '.', '8', 0x0,
3634
3635 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00,
3636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3637 };
3638
3639 SvGlobalName aGName(MSO_WW8_CLASSID0x00020906L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x46
);
3640 GetWriter().GetStorage().SetClass(
3641 aGName, SotClipboardFormatId::NONE, "Microsoft Word-Document");
3642 tools::SvRef<SotStorageStream> xStor( GetWriter().GetStorage().OpenSotStream(sCompObj"\1CompObj") );
3643 xStor->WriteBytes(pData, sizeof(pData));
3644
3645 SwDocShell* pDocShell = m_rDoc.GetDocShell ();
3646 OSL_ENSURE(pDocShell, "no SwDocShell")do { if (true && (!(pDocShell))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "3646" ": "), "%s", "no SwDocShell"); } } while (false)
;
3647
3648 if (!pDocShell) return;
3649
3650 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3651 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
3652 uno::Reference<document::XDocumentProperties> xDocProps(
3653 xDPS->getDocumentProperties());
3654 OSL_ENSURE(xDocProps.is(), "DocumentProperties is null")do { if (true && (!(xDocProps.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "3654" ": "), "%s", "DocumentProperties is null"); } } while
(false)
;
3655
3656 if (!xDocProps.is())
3657 return;
3658
3659 if ( SvtFilterOptions::Get().IsEnableWordPreview() )
3660 {
3661 std::shared_ptr<GDIMetaFile> xMetaFile =
3662 pDocShell->GetPreviewMetaFile();
3663 uno::Sequence<sal_Int8> metaFile(
3664 sfx2::convertMetaFile(xMetaFile.get()));
3665 sfx2::SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
3666 }
3667 else
3668 sfx2::SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
3669}
3670
3671ErrCode SwWW8Writer::WriteStorage()
3672{
3673 tools::SvRef<SotStorage> pOrigStg;
3674 uno::Reference< packages::XPackageEncryption > xPackageEncryption;
3675 std::shared_ptr<SvStream> pSotStorageStream;
3676 uno::Sequence< beans::NamedValue > aEncryptionData;
3677 if (mpMedium)
3678 {
3679 // Check for specific encryption requests
3680 const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mpMedium->GetItemSet(), SID_ENCRYPTIONDATA(5000 + 1722), false);
3681 if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData))
3682 {
3683 ::comphelper::SequenceAsHashMap aHashData(aEncryptionData);
3684 OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString());
3685
3686 if (sCryptoType.getLength())
3687 {
3688 uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
3689 uno::Sequence<uno::Any> aArguments{
3690 uno::makeAny(beans::NamedValue("Binary", uno::makeAny(true))) };
3691 xPackageEncryption.set(
3692 xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
3693 "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY);
3694
3695 if (xPackageEncryption.is())
3696 {
3697 // We have an encryptor
3698 // Create new temporary storage for content
3699 pOrigStg = m_pStg;
3700 pSotStorageStream = std::make_shared<SvMemoryStream>();
3701 m_pStg = new SotStorage(*pSotStorageStream);
3702 }
3703 }
3704 }
3705 }
3706
3707 ErrCode nErrorCode = WriteStorageImpl();
3708
3709 if (xPackageEncryption.is())
3710 {
3711 m_pStg->Commit();
3712 pSotStorageStream->Seek(0);
3713
3714 // Encrypt data written into temporary storage
3715 xPackageEncryption->setupEncryption(aEncryptionData);
3716
3717 uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pSotStorageStream.get(), false));
3718 uno::Sequence<beans::NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream);
3719
3720 m_pStg = pOrigStg;
3721 for (const beans::NamedValue & aStreamData : std::as_const(aStreams))
3722 {
3723 // To avoid long paths split and open substorages recursively
3724 // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09
3725 tools::SvRef<SotStorage> pStorage = m_pStg.get();
3726 OUString sFileName;
3727 sal_Int32 idx = 0;
3728 while (pStorage && idx >= 0)
3729 {
3730 OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx);
3731 if (!sPathElem.isEmpty())
3732 {
3733 if (idx < 0)
3734 {
3735 sFileName = sPathElem;
3736 }
3737 else
3738 {
3739 pStorage = pStorage->OpenSotStorage(sPathElem);
3740 if (!pStorage)
3741 break;
3742 }
3743 }
3744 };
3745
3746 if (!pStorage)
3747 {
3748 nErrorCode = ERRCODE_IO_GENERALErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 );
3749 break;
3750 }
3751
3752 tools::SvRef<SotStorageStream> pStream = pStorage->OpenSotStream(sFileName);
3753 if (!pStream)
3754 {
3755 nErrorCode = ERRCODE_IO_GENERALErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 );
3756 break;
3757 }
3758 uno::Sequence<sal_Int8> aStreamContent;
3759 aStreamData.Value >>= aStreamContent;
3760 size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength());
3761 if (nBytesWritten != static_cast<size_t>(aStreamContent.getLength()))
3762 {
3763 nErrorCode = ERRCODE_IO_CANTWRITEErrCode( ErrCodeArea::Io, ErrCodeClass::Write, 16 );
3764 break;
3765 }
3766 }
3767 }
3768
3769 return nErrorCode;
3770}
3771ErrCode SwWW8Writer::WriteStorageImpl()
3772{
3773 // #i34818# - update layout (if present), for SwWriteTable
3774 SwViewShell* pViewShell = m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
3775 if( pViewShell != nullptr )
3776 pViewShell->CalcLayout();
3777
3778 long nMaxNode = m_pDoc->GetNodes().Count();
3779 ::StartProgress( STR_STATSTR_W4WWRITEreinterpret_cast<char const *>("STR_STATSTR_W4WWRITE" "\004"
u8"Exporting document...")
, 0, nMaxNode, m_pDoc->GetDocShell() );
3780
3781 // Respect table at the beginning of the document
3782 {
3783 SwTableNode* pTNd = m_pCurrentPam->GetNode().FindTableNode();
3784 if( pTNd && m_bWriteAll )
3785 // start with the table node !!
3786 m_pCurrentPam->GetPoint()->nNode = *pTNd;
3787 }
3788
3789 // Do the actual export
3790 ErrCode err = ERRCODE_NONEErrCode(0);
3791 {
3792 bool bDot = mpMedium->GetFilter()->GetName().endsWith("Vorlage");
3793 WW8Export aExport(this, *m_pDoc, m_pCurrentPam, m_pOrigPam, bDot);
3794 m_pExport = &aExport;
3795 err = aExport.ExportDocument( m_bWriteAll );
3796 m_pExport = nullptr;
3797 }
3798
3799 ::EndProgress( m_pDoc->GetDocShell() );
3800 return err;
3801}
3802
3803ErrCode SwWW8Writer::WriteMedium( SfxMedium& )
3804{
3805 return WriteStorage();
3806}
3807
3808ErrCode SwWW8Writer::Write( SwPaM& rPaM, SfxMedium& rMed,
3809 const OUString* pFileName )
3810{
3811 mpMedium = &rMed;
3812 ErrCode nRet = StgWriter::Write( rPaM, rMed, pFileName );
3813 mpMedium = nullptr;
3814 return nRet;
3815}
3816
3817MSWordExportBase::MSWordExportBase( SwDoc& rDocument, std::shared_ptr<SwUnoCursor> & pCurrentPam, SwPaM* pOriginalPam )
3818 : m_aMainStg(sMainStreamOUString("WordDocument"))
3819 , m_pISet(nullptr)
3820 , m_pPiece(nullptr)
3821 , m_pTopNodeOfHdFtPage(nullptr)
3822 , m_pBkmks(nullptr)
3823 , m_pRedlAuthors(nullptr)
3824 , m_pTableInfo(std::make_shared<ww8::WW8TableInfo>())
3825 , m_nCharFormatStart(0)
3826 , m_nFormatCollStart(0)
3827 , m_nStyleBeforeFly(0)
3828 , m_nLastFormatId(0)
3829 , m_nUniqueList(0)
3830 , m_nHdFtIndex(0)
3831 , m_nOrigRedlineFlags(RedlineFlags::NONE)
3832 , m_bOrigShowChanges(true)
3833 , m_pCurrentPageDesc(nullptr)
3834 , m_bFirstTOCNodeWithSection(false)
3835 , m_pChpIter(nullptr)
3836 , m_pAtn(nullptr)
3837 , m_pTextBxs(nullptr)
3838 , m_pHFTextBxs(nullptr)
3839 , m_pParentFrame(nullptr)
3840 , m_pFlyOffset(nullptr)
3841 , m_eNewAnchorType(RndStdIds::FLY_AS_CHAR)
3842 , m_pStyAttr(nullptr)
3843 , m_pOutFormatNode(nullptr)
3844 , m_pCurrentStyle(nullptr)
3845 , m_pSdrObjs(nullptr)
3846 , m_pHFSdrObjs(nullptr)
3847 , m_pEscher(nullptr)
3848 , m_nTextTyp(0)
3849 , m_bStyDef(false)
3850 , m_bBreakBefore(false)
3851 , m_bOutKF(false)
3852 , m_bOutFlyFrameAttrs(false)
3853 , m_bOutPageDescs(false)
3854 , m_bOutFirstPage(false)
3855 , m_bOutTable(false)
3856 , m_bOutGrf(false)
3857 , m_bInWriteEscher(false)
3858 , m_bStartTOX(false)
3859 , m_bInWriteTOX(false)
3860 , m_bFootnoteAtTextEnd(false)
3861 , m_bEndAtTextEnd(false)
3862 , m_bHasHdr(false)
3863 , m_bHasFtr(false)
3864 , m_bSubstituteBullets(true)
3865 , m_bTabInTOC(false)
3866 , m_bHideTabLeaderAndPageNumbers(false)
3867 , m_bExportModeRTF(false)
3868 , m_bFontSizeWritten(false)
3869 , m_bAddFootnoteTab(false)
3870 , m_rDoc(rDocument)
3871 , m_nCurStart(pCurrentPam->GetPoint()->nNode.GetIndex())
3872 , m_nCurEnd(pCurrentPam->GetMark()->nNode.GetIndex())
3873 , m_pCurPam(pCurrentPam)
3874 , m_pOrigPam(pOriginalPam)
3875{
3876}
3877
3878MSWordExportBase::~MSWordExportBase()
3879{
3880 if (m_pUsedNumTable) // all used NumRules
3881 {
3882 // clear the part of the list array that was copied from the document
3883 // - it's an auto delete array, so the rest of the array which are
3884 // duplicated lists that were added during the export will be deleted.
3885 m_pUsedNumTable->erase(m_pUsedNumTable->begin(), m_pUsedNumTable->begin() + m_pUsedNumTable->size() - m_nUniqueList);
3886 m_pUsedNumTable.reset();
3887 }
3888 m_pOLEExp.reset();
3889 m_pOCXExp.reset();
3890}
3891
3892WW8Export::WW8Export( SwWW8Writer *pWriter,
3893 SwDoc& rDocument, std::shared_ptr<SwUnoCursor> & pCurrentPam, SwPaM* pOriginalPam,
3894 bool bDot )
3895 : MSWordExportBase( rDocument, pCurrentPam, pOriginalPam )
3896 , pTableStrm(nullptr)
3897 , pDataStrm(nullptr)
3898 , m_bDot(bDot)
3899 , m_pWriter(pWriter)
3900 , m_pAttrOutput(new WW8AttributeOutput(*this))
3901{
3902}
3903
3904WW8Export::~WW8Export()
3905{
3906}
3907
3908AttributeOutputBase& WW8Export::AttrOutput() const
3909{
3910 return *m_pAttrOutput;
3911}
3912
3913MSWordSections& WW8Export::Sections() const
3914{
3915 return *pSepx;
3916}
3917
3918SwWW8Writer::SwWW8Writer(const OUString& rFltName, const OUString& rBaseURL)
3919 : StgWriter(),
3920 m_pExport( nullptr ),
3921 mpMedium( nullptr )
3922{
3923 assert(rFltName == FILTER_WW8)(static_cast <bool> (rFltName == "CWW8") ? void (0) : __assert_fail
("rFltName == FILTER_WW8", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
, 3923, __extension__ __PRETTY_FUNCTION__))
; // WW6/7 export was removed
3924 (void)rFltName;
3925 SetBaseURL( rBaseURL );
3926}
3927
3928SwWW8Writer::~SwWW8Writer()
3929{
3930}
3931
3932extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) sal_uInt32 SaveOrDelMSVBAStorage_ww8( SfxObjectShell& rDoc, SotStorage& rStor, sal_Bool bSaveInto, const OUString& rStorageName )
3933{
3934 SvxImportMSVBasic aTmp( rDoc, rStor );
3935 return sal_uInt32(aTmp.SaveOrDelMSVBAStorage( bSaveInto, rStorageName ));
3936}
3937
3938extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) void ExportDOC( const OUString& rFltName, const OUString& rBaseURL, WriterRef& xRet )
3939{
3940 xRet = new SwWW8Writer( rFltName, rBaseURL );
3941}
3942
3943extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) sal_uInt32 GetSaveWarningOfMSVBAStorage_ww8( SfxObjectShell &rDocS )
3944{
3945 return sal_uInt32(SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( rDocS ));
3946}
3947
3948bool WW8_WrPlcFootnoteEdn::WriteText( WW8Export& rWrt )
3949{
3950 bool bRet = false;
3951 if (TXT_FTN == nTyp)
3952 {
3953 bRet = WriteGenericText( rWrt, TXT_FTN, rWrt.pFib->m_ccpFootnote );
3954 rWrt.m_pFieldFootnote->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3955 rWrt.pFib->m_ccpText );
3956 }
3957 else
3958 {
3959 bRet = WriteGenericText( rWrt, TXT_EDN, rWrt.pFib->m_ccpEdn );
3960 rWrt.m_pFieldEdn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3961 rWrt.pFib->m_ccpText + rWrt.pFib->m_ccpFootnote
3962 + rWrt.pFib->m_ccpHdr + rWrt.pFib->m_ccpAtn );
3963 }
3964 return bRet;
3965}
3966
3967void WW8_WrPlcFootnoteEdn::WritePlc( WW8Export& rWrt ) const
3968{
3969 if( TXT_FTN == nTyp )
3970 {
3971 WriteGenericPlc( rWrt, TXT_FTN, rWrt.pFib->m_fcPlcffndText,
3972 rWrt.pFib->m_lcbPlcffndText, rWrt.pFib->m_fcPlcffndRef,
3973 rWrt.pFib->m_lcbPlcffndRef );
3974 }
3975 else
3976 {
3977 WriteGenericPlc( rWrt, TXT_EDN, rWrt.pFib->m_fcPlcfendText,
3978 rWrt.pFib->m_lcbPlcfendText, rWrt.pFib->m_fcPlcfendRef,
3979 rWrt.pFib->m_lcbPlcfendRef );
3980 }
3981}
3982
3983bool WW8_WrPlcAnnotations::WriteText( WW8Export& rWrt )
3984{
3985 bool bRet = WriteGenericText( rWrt, TXT_ATN, rWrt.pFib->m_ccpAtn );
3986 rWrt.m_pFieldAtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3987 rWrt.pFib->m_ccpText + rWrt.pFib->m_ccpFootnote
3988 + rWrt.pFib->m_ccpHdr );
3989 return bRet;
3990}
3991
3992void WW8_WrPlcAnnotations::WritePlc( WW8Export& rWrt ) const
3993{
3994 WriteGenericPlc( rWrt, TXT_ATN, rWrt.pFib->m_fcPlcfandText,
3995 rWrt.pFib->m_lcbPlcfandText, rWrt.pFib->m_fcPlcfandRef,
3996 rWrt.pFib->m_lcbPlcfandRef );
3997}
3998
3999void WW8_WrPlcTextBoxes::WritePlc( WW8Export& rWrt ) const
4000{
4001 if( TXT_TXTBOX == nTyp )
4002 {
4003 WriteGenericPlc( rWrt, nTyp, rWrt.pFib->m_fcPlcftxbxBkd,
4004 rWrt.pFib->m_lcbPlcftxbxBkd, rWrt.pFib->m_fcPlcftxbxText,
4005 rWrt.pFib->m_lcbPlcftxbxText );
4006 }
4007 else
4008 {
4009 WriteGenericPlc( rWrt, nTyp, rWrt.pFib->m_fcPlcfHdrtxbxBkd,
4010 rWrt.pFib->m_lcbPlcfHdrtxbxBkd, rWrt.pFib->m_fcPlcfHdrtxbxText,
4011 rWrt.pFib->m_lcbPlcfHdrtxbxText );
4012 }
4013}
4014
4015void WW8Export::RestoreMacroCmds()
4016{
4017 pFib->m_fcCmds = pTableStrm->Tell();
4018
4019 uno::Reference < embed::XStorage > xSrcRoot(m_rDoc.GetDocShell()->GetStorage());
4020 try
4021 {
4022 uno::Reference < io::XStream > xSrcStream =
4023 xSrcRoot->openStreamElement( SL::aMSMacroCmds, embed::ElementModes::READ );
4024 std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( xSrcStream );
4025
4026 if ( pStream && ERRCODE_NONEErrCode(0) == pStream->GetError())
4027 {
4028 pFib->m_lcbCmds = pStream->TellEnd();
4029 pStream->Seek(0);
4030
4031 std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[pFib->m_lcbCmds] );
4032 bool bReadOk = checkRead(*pStream, pBuffer.get(), pFib->m_lcbCmds);
4033 if (bReadOk)
4034 pTableStrm->WriteBytes(pBuffer.get(), pFib->m_lcbCmds);
4035 }
4036 }
4037 catch ( const uno::Exception& )
4038 {
4039 }
4040
4041 // set len to FIB
4042 pFib->m_lcbCmds = pTableStrm->Tell() - pFib->m_fcCmds;
4043}
4044
4045void WW8SHDLong::Write( WW8Export& rExport )
4046{
4047 rExport.InsUInt32( m_cvFore );
4048 rExport.InsUInt32( m_cvBack );
4049 rExport.InsUInt16( 0 ); // ipat
4050}
4051
4052void WW8Export::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
4053{
4054 const ::sw::mark::IFieldmark* pFieldmark = &rFieldmark;
4055 const ::sw::mark::ICheckboxFieldmark* pAsCheckbox = dynamic_cast< const ::sw::mark::ICheckboxFieldmark* >( pFieldmark );
4056
4057 if ( ! ( rFieldmark.GetFieldname() == ODF_FORMTEXT"vnd.oasis.opendocument.field.FORMTEXT" ||
4058 rFieldmark.GetFieldname() == ODF_FORMDROPDOWN"vnd.oasis.opendocument.field.FORMDROPDOWN" ||
4059 rFieldmark.GetFieldname() == ODF_FORMCHECKBOX"vnd.oasis.opendocument.field.FORMCHECKBOX" ) )
4060 {
4061 SAL_WARN( "sw.ww8", "unknown field type" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "unknown field type")
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4061" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "unknown field type"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"unknown field type"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4061" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "unknown field type") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4061" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "unknown field type"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"unknown field type"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4061" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4062 return;
4063 }
4064
4065 int type = 0; // TextFieldmark
4066 if ( pAsCheckbox )
4067 type = 1;
4068 if ( rFieldmark.GetFieldname() == ODF_FORMDROPDOWN"vnd.oasis.opendocument.field.FORMDROPDOWN" )
4069 type=2;
4070
4071 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pParameter = rFieldmark.GetParameters()->find("name");
4072 OUString ffname;
4073 if ( pParameter != rFieldmark.GetParameters()->end() )
4074 {
4075 OUString aName;
4076 pParameter->second >>= aName;
4077 const sal_Int32 nLen = std::min( sal_Int32(20), aName.getLength() );
4078 ffname = aName.copy(0, nLen);
4079 }
4080
4081 sal_uInt64 nDataStt = pDataStrm->Tell();
4082 m_pChpPlc->AppendFkpEntry(Strm().Tell());
4083
4084 WriteChar(0x01);
4085 static sal_uInt8 aArr1[] =
4086 {
4087 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
4088
4089 0x06, 0x08, 0x01, // sprmCFData
4090 0x55, 0x08, 0x01, // sprmCFSpec
4091 0x02, 0x08, 0x01 // sprmCFFieldVanish
4092 };
4093 sal_uInt8* pDataAdr = aArr1 + 2;
4094 Set_UInt32(pDataAdr, nDataStt);
4095
4096 m_pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aArr1 ), aArr1 );
4097
4098 struct FFDataHeader
4099 {
4100 sal_uInt32 version;
4101 sal_uInt16 bits;
4102 sal_uInt16 cch;
4103 sal_uInt16 hps;
4104 FFDataHeader() : version( 0xFFFFFFFF ), bits(0), cch(0), hps(0) {}
4105 };
4106
4107 FFDataHeader aFieldHeader;
4108 aFieldHeader.bits |= (type & 0x03);
4109
4110 sal_Int32 ffres = 0; // rFieldmark.GetFFRes();
4111 if ( pAsCheckbox && pAsCheckbox->IsChecked() )
4112 ffres = 1;
4113 else if ( type == 2 )
4114 {
4115 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pResParameter = rFieldmark.GetParameters()->find(ODF_FORMDROPDOWN_RESULT"Dropdown_Selected");
4116 if(pResParameter != rFieldmark.GetParameters()->end())
4117 pResParameter->second >>= ffres;
4118 else
4119 ffres = 0;
4120 }
4121 aFieldHeader.bits |= ( (ffres<<2) & 0x7C );
4122
4123 OUString ffdeftext;
4124 OUString ffformat;
4125 OUString ffhelptext = rFieldmark.GetFieldHelptext();
4126 if ( ffhelptext.getLength() > 255 )
4127 ffhelptext = ffhelptext.copy(0, 255);
4128 OUString ffstattext;
4129 OUString ffentrymcr;
4130 OUString ffexitmcr;
4131 if (type == 0) // iTypeText
4132 {
4133 sal_uInt16 nType = 0;
4134 pParameter = rFieldmark.GetParameters()->find("Type");
4135 if ( pParameter != rFieldmark.GetParameters()->end() )
4136 {
4137 OUString aType;
4138 pParameter->second >>= aType;
4139 if ( aType == "number" ) nType = 1;
4140 else if ( aType == "date" ) nType = 2;
4141 else if ( aType == "currentTime" ) nType = 3;
4142 else if ( aType == "currentDate" ) nType = 4;
4143 else if ( aType == "calculated" ) nType = 5;
4144 aFieldHeader.bits |= nType<<11; // FFDataBits-F 00111000 00000000
4145 }
4146
4147 if ( nType < 3 || nType == 5 ) // not currentTime or currentDate
4148 {
4149 pParameter = rFieldmark.GetParameters()->find("Content");
4150 if ( pParameter != rFieldmark.GetParameters()->end() )
4151 {
4152 OUString aDefaultText;
4153 pParameter->second >>= aDefaultText;
4154 const sal_Int32 nLen = std::min( sal_Int32(255), aDefaultText.getLength() );
4155 ffdeftext = aDefaultText.copy (0, nLen);
4156 }
4157 }
4158
4159 pParameter = rFieldmark.GetParameters()->find("MaxLength");
4160 if ( pParameter != rFieldmark.GetParameters()->end() )
4161 {
4162 sal_uInt16 nLength = 0;
4163 pParameter->second >>= nLength;
4164 nLength = std::min( sal_uInt16(32767), nLength );
4165 aFieldHeader.cch = nLength;
4166 }
4167
4168 pParameter = rFieldmark.GetParameters()->find("Format");
4169 if ( pParameter != rFieldmark.GetParameters()->end() )
4170 {
4171 OUString aFormat;
4172 pParameter->second >>= aFormat;
4173 const sal_Int32 nLen = std::min( sal_Int32(64), aFormat.getLength() );
4174 ffformat = aFormat.copy(0, nLen);
4175 }
4176 }
4177
4178 pParameter = rFieldmark.GetParameters()->find("Help"); //help
4179 if ( ffhelptext.isEmpty() && pParameter != rFieldmark.GetParameters()->end() )
4180 {
4181 OUString aHelpText;
4182 pParameter->second >>= aHelpText;
4183 const sal_Int32 nLen = std::min( sal_Int32(255), aHelpText.getLength() );
4184 ffhelptext = aHelpText.copy (0, nLen);
4185 }
4186 if ( !ffhelptext.isEmpty() )
4187 aFieldHeader.bits |= 0x1<<7;
4188
4189 pParameter = rFieldmark.GetParameters()->find("Description"); // doc tooltip
4190 if ( pParameter == rFieldmark.GetParameters()->end() )
4191 pParameter = rFieldmark.GetParameters()->find("Hint"); //docx tooltip
4192 if ( pParameter != rFieldmark.GetParameters()->end() )
4193 {
4194 OUString aStatusText;
4195 pParameter->second >>= aStatusText;
4196 const sal_Int32 nLen = std::min( sal_Int32(138), aStatusText.getLength() );
4197 ffstattext = aStatusText.copy (0, nLen);
4198 }
4199 if ( !ffstattext.isEmpty() )
4200 aFieldHeader.bits |= 0x1<<8;
4201
4202 pParameter = rFieldmark.GetParameters()->find("EntryMacro");
4203 if ( pParameter != rFieldmark.GetParameters()->end() )
4204 {
4205 OUString aEntryMacro;
4206 pParameter->second >>= aEntryMacro;
4207 const sal_Int32 nLen = std::min( sal_Int32(32), aEntryMacro.getLength() );
4208 ffentrymcr = aEntryMacro.copy (0, nLen);
4209 }
4210
4211 pParameter = rFieldmark.GetParameters()->find("ExitMacro");
4212 if ( pParameter != rFieldmark.GetParameters()->end() )
4213 {
4214 OUString aExitMacro;
4215 pParameter->second >>= aExitMacro;
4216 const sal_Int32 nLen = std::min( sal_Int32(32), aExitMacro.getLength() );
4217 ffexitmcr = aExitMacro.copy (0, nLen);
4218 }
4219
4220 std::vector< OUString > aListItems;
4221 if (type==2)
4222 {
4223 aFieldHeader.bits |= 0x8000; // ffhaslistbox
4224 const ::sw::mark::IFieldmark::parameter_map_t* const pParameters = rFieldmark.GetParameters();
4225 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY"Dropdown_ListEntry");
4226 if(pListEntries != pParameters->end())
4227 {
4228 uno::Sequence< OUString > vListEntries;
4229 pListEntries->second >>= vListEntries;
4230 copy(vListEntries.begin(), vListEntries.end(), back_inserter(aListItems));
4231 }
4232 }
4233
4234 const sal_uInt8 aFieldData[] =
4235 {
4236 0x44,0, // the start of "next" data
4237 0,0,0,0,0,0,0,0,0,0, // PIC-Structure! /10
4238 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
4239 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
4240 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
4241 0,0,0,0, // / /4
4242 };
4243 sal_uInt32 slen = sizeof(sal_uInt32)
4244 + sizeof(aFieldData)
4245 + sizeof( aFieldHeader.version ) + sizeof( aFieldHeader.bits ) + sizeof( aFieldHeader.cch ) + sizeof( aFieldHeader.hps )
4246 + 2*ffname.getLength() + 4
4247 + 2*ffformat.getLength() + 4
4248 + 2*ffhelptext.getLength() + 4
4249 + 2*ffstattext.getLength() + 4
4250 + 2*ffentrymcr.getLength() + 4
4251 + 2*ffexitmcr.getLength() + 4;
4252 if ( type )
4253 slen += 2; // wDef
4254 else
4255 slen += 2*ffdeftext.getLength() + 4; //xstzTextDef
4256 if ( type==2 ) {
4257 slen += 2; // sttb ( fExtend )
4258 slen += 4; // for num of list items
4259 const int items = aListItems.size();
4260 for( int i = 0; i < items; i++ ) {
4261 OUString item = aListItems[i];
4262 slen += 2 * item.getLength() + 2;
4263 }
4264 }
4265
4266 pDataStrm->WriteUInt32( slen );
4267
4268 int len = sizeof( aFieldData );
4269 OSL_ENSURE( len == 0x44-sizeof(sal_uInt32), "SwWW8Writer::WriteFormData(..) - wrong aFieldData length" )do { if (true && (!(len == 0x44-sizeof(sal_uInt32))))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4269" ": "), "%s", "SwWW8Writer::WriteFormData(..) - wrong aFieldData length"
); } } while (false)
;
4270 pDataStrm->WriteBytes( aFieldData, len );
4271
4272 pDataStrm->WriteUInt32( aFieldHeader.version ).WriteUInt16( aFieldHeader.bits ).WriteUInt16( aFieldHeader.cch ).WriteUInt16( aFieldHeader.hps );
4273
4274 SwWW8Writer::WriteString_xstz( *pDataStrm, ffname, true ); // Form field name
4275
4276 if ( !type )
4277 SwWW8Writer::WriteString_xstz( *pDataStrm, ffdeftext, true );
4278 if ( type )
4279 pDataStrm->WriteUInt16( 0 );
4280
4281 SwWW8Writer::WriteString_xstz( *pDataStrm, ffformat, true );
4282 SwWW8Writer::WriteString_xstz( *pDataStrm, ffhelptext, true );
4283 SwWW8Writer::WriteString_xstz( *pDataStrm, ffstattext, true );
4284 SwWW8Writer::WriteString_xstz( *pDataStrm, ffentrymcr, true );
4285 SwWW8Writer::WriteString_xstz( *pDataStrm, ffexitmcr, true );
4286 if (type==2) {
4287 pDataStrm->WriteUInt16( 0xFFFF );
4288 const int items=aListItems.size();
4289 pDataStrm->WriteUInt32( items );
4290 for(int i=0;i<items;i++) {
4291 OUString item=aListItems[i];
4292 SwWW8Writer::WriteString_xstz( *pDataStrm, item, false );
4293 }
4294 }
4295}
4296
4297void WW8Export::WriteHyperlinkData( const sw::mark::IFieldmark& /*rFieldmark*/ )
4298{
4299 //@TODO implement me !!!
4300}
4301
4302void WW8AttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
4303{
4304 SVBT16 nStyle;
4305 ShortToSVBT16( m_rWW8Export.m_nStyleBeforeFly, nStyle );
4306
4307#ifdef DBG_UTIL
4308 SAL_INFO( "sw.ww8", "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner->toString())do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "<OutWW8_TableNodeInfoInner>"
<< pNodeInfoInner->toString()) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4308" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<OutWW8_TableNodeInfoInner>" <<
pNodeInfoInner->toString()), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "<OutWW8_TableNodeInfoInner>"
<< pNodeInfoInner->toString(); ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4308" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner
->toString()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4308" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<OutWW8_TableNodeInfoInner>" <<
pNodeInfoInner->toString()), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "<OutWW8_TableNodeInfoInner>"
<< pNodeInfoInner->toString(); ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4308" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4309#endif
4310
4311 m_rWW8Export.pO->clear();
4312
4313 sal_uInt32 nShadowsBefore = pNodeInfoInner->getShadowsBefore();
4314 if (nShadowsBefore > 0)
4315 {
4316 ww8::WW8TableNodeInfoInner::Pointer_t
4317 pTmpNodeInfoInner = std::make_shared<ww8::WW8TableNodeInfoInner>(nullptr);
4318
4319 pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
4320 pTmpNodeInfoInner->setEndOfCell(true);
4321
4322 for (sal_uInt32 n = 0; n < nShadowsBefore; ++n)
4323 {
4324 m_rWW8Export.WriteCR(pTmpNodeInfoInner);
4325
4326 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4327 TableInfoCell(pTmpNodeInfoInner);
4328 m_rWW8Export.m_pPapPlc->AppendFkpEntry
4329 ( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4330
4331 m_rWW8Export.pO->clear();
4332 }
4333 }
4334
4335 if (pNodeInfoInner->isEndOfCell())
4336 {
4337 SAL_INFO( "sw.ww8", "<endOfCell/>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "<endOfCell/>")
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4337" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<endOfCell/>"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"<endOfCell/>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4337" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "<endOfCell/>") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4337" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<endOfCell/>"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"<endOfCell/>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4337" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4338
4339 m_rWW8Export.WriteCR(pNodeInfoInner);
4340
4341 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4342 TableInfoCell(pNodeInfoInner);
4343 m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4344
4345 m_rWW8Export.pO->clear();
4346 }
4347
4348 sal_uInt32 nShadowsAfter = pNodeInfoInner->getShadowsAfter();
4349 if (nShadowsAfter > 0)
4350 {
4351 ww8::WW8TableNodeInfoInner::Pointer_t
4352 pTmpNodeInfoInner= std::make_shared<ww8::WW8TableNodeInfoInner>(nullptr);
4353
4354 pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
4355 pTmpNodeInfoInner->setEndOfCell(true);
4356
4357 for (sal_uInt32 n = 0; n < nShadowsAfter; ++n)
4358 {
4359 m_rWW8Export.WriteCR(pTmpNodeInfoInner);
4360
4361 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4362 TableInfoCell(pTmpNodeInfoInner);
4363 m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4364
4365 m_rWW8Export.pO->clear();
4366 }
4367 }
4368
4369 if (pNodeInfoInner->isEndOfLine())
4370 {
4371 SAL_INFO( "sw.ww8", "<endOfLine/>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "<endOfLine/>")
== 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4371" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<endOfLine/>"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"<endOfLine/>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4371" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "<endOfLine/>") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4371" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<endOfLine/>"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"<endOfLine/>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4371" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4372
4373 TableRowEnd(pNodeInfoInner->getDepth());
4374
4375 ShortToSVBT16(0, nStyle);
4376 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4377 TableInfoRow(pNodeInfoInner);
4378 m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4379
4380 m_rWW8Export.pO->clear();
4381 }
4382 SAL_INFO( "sw.ww8", "</OutWW8_TableNodeInfoInner>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "</OutWW8_TableNodeInfoInner>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4382" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutWW8_TableNodeInfoInner>"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "</OutWW8_TableNodeInfoInner>"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4382" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "</OutWW8_TableNodeInfoInner>") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4382" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutWW8_TableNodeInfoInner>"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "</OutWW8_TableNodeInfoInner>"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4382" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4383}
4384
4385void MSWordExportBase::OutputStartNode( const SwStartNode & rNode)
4386{
4387
4388 ww8::WW8TableNodeInfo::Pointer_t pNodeInfo =
4389 m_pTableInfo->getTableNodeInfo( &rNode );
4390
4391 if (pNodeInfo)
4392 {
4393#ifdef DBG_UTIL
4394 SAL_INFO( "sw.ww8", pNodeInfo->toString())do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << pNodeInfo->toString
()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4394" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << pNodeInfo->toString()), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
pNodeInfo->toString(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4394" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << pNodeInfo->toString()) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4394" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << pNodeInfo->toString()), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
pNodeInfo->toString(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4394" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4395#endif
4396 const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
4397 ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aIt(aInners.rbegin());
4398 ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aEnd(aInners.rend());
4399 while (aIt != aEnd)
4400 {
4401 ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
4402
4403 AttrOutput().TableNodeInfoInner(pInner);
4404 ++aIt;
4405 }
4406 }
4407 SAL_INFO( "sw.ww8", "</OutWW8_SwStartNode>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "</OutWW8_SwStartNode>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4407" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutWW8_SwStartNode>"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "</OutWW8_SwStartNode>"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4407" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "</OutWW8_SwStartNode>") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4407" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutWW8_SwStartNode>"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "</OutWW8_SwStartNode>"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4407" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4408}
4409
4410void MSWordExportBase::OutputEndNode( const SwEndNode &rNode )
4411{
4412#ifdef DBG_UTIL
4413 SAL_INFO( "sw.ww8", "<OutWW8_SwEndNode>" << dbg_out(&rNode))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "<OutWW8_SwEndNode>"
<< dbg_out(&rNode)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4413" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<OutWW8_SwEndNode>" << dbg_out
(&rNode)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "<OutWW8_SwEndNode>" <<
dbg_out(&rNode); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4413" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "<OutWW8_SwEndNode>" << dbg_out(&
rNode)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4413" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "<OutWW8_SwEndNode>" << dbg_out
(&rNode)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "<OutWW8_SwEndNode>" <<
dbg_out(&rNode); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4413" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4414#endif
4415
4416 ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = m_pTableInfo->getTableNodeInfo( &rNode );
4417
4418 if (pNodeInfo)
4419 {
4420#ifdef DBG_UTIL
4421 SAL_INFO( "sw.ww8", pNodeInfo->toString())do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << pNodeInfo->toString
()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), (
"sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4421" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << pNodeInfo->toString()), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
pNodeInfo->toString(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4421" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << pNodeInfo->toString()) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4421" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << pNodeInfo->toString()), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
pNodeInfo->toString(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4421" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4422#endif
4423 const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
4424 for (const auto& rEntry : aInners)
4425 {
4426 ww8::WW8TableNodeInfoInner::Pointer_t pInner = rEntry.second;
4427 AttrOutput().TableNodeInfoInner(pInner);
4428 }
4429 }
4430 SAL_INFO( "sw.ww8", "</OutWW8_SwEndNode>" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "</OutWW8_SwEndNode>"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4430" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutWW8_SwEndNode>"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"</OutWW8_SwEndNode>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4430" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "</OutWW8_SwEndNode>") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4430" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "</OutWW8_SwEndNode>"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"</OutWW8_SwEndNode>"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx"
":" "4430" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4431}
4432
4433const NfKeywordTable & MSWordExportBase::GetNfKeywordTable()
4434{
4435 if (m_pKeyMap == nullptr)
4436 {
4437 m_pKeyMap = std::make_shared<NfKeywordTable>();
4438 NfKeywordTable & rKeywordTable = *m_pKeyMap;
4439 rKeywordTable[NF_KEY_D] = "d";
4440 rKeywordTable[NF_KEY_DD] = "dd";
4441 rKeywordTable[NF_KEY_DDD] = "ddd";
4442 rKeywordTable[NF_KEY_DDDD] = "dddd";
4443 rKeywordTable[NF_KEY_M] = "M";
4444 rKeywordTable[NF_KEY_MM] = "MM";
4445 rKeywordTable[NF_KEY_MMM] = "MMM";
4446 rKeywordTable[NF_KEY_MMMM] = "MMMM";
4447 rKeywordTable[NF_KEY_NN] = "ddd";
4448 rKeywordTable[NF_KEY_NNN] = "dddd";
4449 rKeywordTable[NF_KEY_NNNN] = "dddd";
4450 rKeywordTable[NF_KEY_YY] = "yy";
4451 rKeywordTable[NF_KEY_YYYY] = "yyyy";
4452 rKeywordTable[NF_KEY_H] = "H";
4453 rKeywordTable[NF_KEY_HH] = "HH";
4454 rKeywordTable[NF_KEY_MI] = "m";
4455 rKeywordTable[NF_KEY_MMI] = "mm";
4456 rKeywordTable[NF_KEY_S] = "s";
4457 rKeywordTable[NF_KEY_SS] = "ss";
4458 rKeywordTable[NF_KEY_AMPM] = "AM/PM";
4459 }
4460
4461 return *m_pKeyMap;
4462}
4463
4464/* vim:set shiftwidth=4 softtabstop=4 expandtab: */