File: | home/maarten/src/libreoffice/core/sw/source/filter/ww8/wrtww8.cxx |
Warning: | line 3792, column 21 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
120 | using namespace css; | |||
121 | using namespace sw::util; | |||
122 | using namespace sw::types; | |||
123 | ||||
124 | /** FKP - Formatted disK Page | |||
125 | */ | |||
126 | class 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 | ||||
143 | public: | |||
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 | |||
165 | class 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 | ||||
171 | public: | |||
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 | ||||
182 | typedef std::map<OUString,long> BKMKNames; | |||
183 | typedef std::pair<bool,OUString> BKMK; | |||
184 | typedef std::pair<long,BKMK> BKMKCP; | |||
185 | typedef std::multimap<long,BKMKCP*> BKMKCPs; | |||
186 | typedef BKMKCPs::iterator CPItr; | |||
187 | ||||
188 | class WW8_WrtBookmarks | |||
189 | { | |||
190 | private: | |||
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 | ||||
198 | public: | |||
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 | ||||
209 | WW8_WrtBookmarks::WW8_WrtBookmarks() | |||
210 | {} | |||
211 | ||||
212 | WW8_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 | ||||
224 | void 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 | ||||
250 | void 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 | ||||
302 | void 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. | |||
326 | class 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 | ||||
335 | public: | |||
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 | ||||
341 | WW8_WrtFactoids::WW8_WrtFactoids() | |||
342 | { | |||
343 | } | |||
344 | ||||
345 | void 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 | ||||
352 | void 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 | ||||
451 | static 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 | ||||
553 | static 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 | /* | |||
565 | Converts the OOo Asian Typography into a best fit match for Microsoft | |||
566 | Asian typography. This structure is actually dumped to disk within the | |||
567 | Dop Writer. Assumption is that rTypo is cleared to 0 on entry | |||
568 | */ | |||
569 | void 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() | |||
749 | const 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 | ||||
771 | const 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 | ||||
786 | WW8_WrPlc1::WW8_WrPlc1( sal_uInt16 nStructSz ) | |||
787 | : pData( new sal_uInt8[ 16 * nStructSz ] ), | |||
788 | nDataLen(16 * nStructSz), | |||
789 | nStructSiz( nStructSz ) | |||
790 | { | |||
791 | } | |||
792 | ||||
793 | WW8_WrPlc1::~WW8_WrPlc1() | |||
794 | { | |||
795 | } | |||
796 | ||||
797 | WW8_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 | ||||
804 | void 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 | ||||
818 | void 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 | ||||
829 | void 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 | ||||
840 | void 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 | ||||
897 | void 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 | ||||
907 | void 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 | ||||
922 | void 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 | ||||
937 | sal_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 | ||||
952 | WW8_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 | ||||
960 | WW8_WrPlcPn::~WW8_WrPlcPn() | |||
961 | { | |||
962 | } | |||
963 | ||||
964 | sal_uInt8 *WW8_WrPlcPn::CopyLastSprms(sal_uInt8 &rLen) | |||
965 | { | |||
966 | WW8_WrFkp& rF = *m_Fkps.back(); | |||
967 | return rF.CopyLastSprms(rLen); | |||
968 | } | |||
969 | ||||
970 | void 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 | ||||
1021 | void 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 | ||||
1042 | void 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 | ||||
1074 | WW8_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 | ||||
1086 | WW8_WrFkp::~WW8_WrFkp() | |||
1087 | { | |||
1088 | delete[] reinterpret_cast<sal_Int32 *>(pFkp); | |||
1089 | delete[] reinterpret_cast<sal_Int32 *>(pOfs); | |||
1090 | } | |||
1091 | ||||
1092 | sal_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 | ||||
1121 | sal_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 | ||||
1149 | bool 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 | ||||
1218 | void 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 | ||||
1238 | void 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 | ||||
1260 | void 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 | ||||
1303 | WW8_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 | ||||
1313 | WW8_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 | |||
1321 | WW8_WrPct::WW8_WrPct(WW8_FC nfcMin) | |||
1322 | : nOldFc(nfcMin) | |||
1323 | { | |||
1324 | AppendPc(nOldFc); | |||
1325 | } | |||
1326 | ||||
1327 | WW8_WrPct::~WW8_WrPct() | |||
1328 | { | |||
1329 | } | |||
1330 | ||||
1331 | // Fill the piece and create a new one | |||
1332 | void 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 | ||||
1353 | void 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 | ||||
1393 | void 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 | ||||
1399 | WW8_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 | ||||
1409 | void 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 )) | |||
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; | |||
1421 | if(dynamic_cast< const ::sw::mark::IFieldmark *>(&rBkmk)) | |||
1422 | continue; | |||
1423 | ||||
1424 | const SwPosition* pPos = &rBkmk.GetMarkPos(); | |||
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 | ||||
1452 | void 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 | ||||
1469 | void 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 | ||||
1479 | void WW8Export::MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo) | |||
1480 | { | |||
1481 | m_pBkmks->MoveFieldMarks(nFrom, nTo); | |||
1482 | } | |||
1483 | ||||
1484 | void WW8Export::AppendBookmark( const OUString& rName ) | |||
1485 | { | |||
1486 | sal_uLong nSttCP = Fc2Cp( Strm().Tell() ); | |||
1487 | m_pBkmks->Append( nSttCP, rName ); | |||
1488 | } | |||
1489 | ||||
1490 | void WW8Export::AppendBookmarkEndWithCorrection( const OUString& rName ) | |||
1491 | { | |||
1492 | sal_uLong nEndCP = Fc2Cp( Strm().Tell() ); | |||
1493 | m_pBkmks->Append( nEndCP - 1, rName ); | |||
1494 | } | |||
1495 | ||||
1496 | std::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 | |||
1512 | int 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 | ||||
1553 | void 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 | |||
1571 | void 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 | ||||
1588 | static sal_uInt8 nAttrMagicIdx = 0; | |||
1589 | void 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 | ||||
1620 | int 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 | ||||
1640 | void 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 | ||||
1647 | sal_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 | ||||
1657 | void 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. | |||
1681 | void 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 | ||||
1689 | void 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 | ||||
1697 | void 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 | ||||
1705 | void 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 | ||||
1715 | void 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 | ||||
1722 | void 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 | ||||
1732 | void 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 | ||||
1745 | void 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 | ||||
1755 | void 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 | ||||
1768 | void 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 | ||||
1788 | void 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 | ||||
1824 | void 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 | ||||
1851 | void 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 | ||||
1861 | void WW8Export::WriteChar( sal_Unicode c ) | |||
1862 | { | |||
1863 | Strm().WriteUInt16( c ); | |||
1864 | } | |||
1865 | ||||
1866 | void 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 | ||||
1883 | void 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 | ||||
1915 | void 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 | ||||
1938 | void 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 | ||||
1956 | void 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 | ||||
1971 | void 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 | ||||
1991 | void 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 | ||||
2038 | static 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 | ||||
2091 | void 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 | ||||
2127 | void 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 | ||||
2147 | void 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 | ||||
2159 | void WW8AttributeOutput::TableRowRedline( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ ) | |||
2160 | { | |||
2161 | } | |||
2162 | ||||
2163 | void WW8AttributeOutput::TableCellRedline( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ ) | |||
2164 | { | |||
2165 | } | |||
2166 | ||||
2167 | void 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 | ||||
2192 | void 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 | ||||
2254 | void 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 | ||||
2292 | void 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 | ||||
2418 | ww8::GridColsPtr AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner ) | |||
2419 | { | |||
2420 | return pTableTextNodeInfoInner->getGridColsOfRow(*this); | |||
2421 | } | |||
2422 | ||||
2423 | ww8::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 | ||||
2429 | void 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 | ||||
2506 | void 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 | ||||
2535 | void 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 | ||||
2620 | void 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 | ||||
2720 | void WW8Export::SectionBreaksAndFrames( const SwTextNode& rNode ) | |||
2721 | { | |||
2722 | // output page/section breaks | |||
2723 | OutputSectionBreaks( rNode.GetpSwAttrSet(), rNode ); | |||
2724 | } | |||
2725 | ||||
2726 | namespace { | |||
2727 | ||||
2728 | class TrackContentToExport | |||
2729 | { | |||
2730 | private: | |||
2731 | SwPaM *m_pCurPam; | |||
2732 | sal_uLong m_nStart, m_nEnd; | |||
2733 | public: | |||
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 | ||||
2772 | void 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 | ||||
2917 | void 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 | ||||
2945 | bool 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 | ||||
2967 | typedef ww8::WW8Sttb< ww8::WW8Struct > WW8SttbAssoc; | |||
2968 | ||||
2969 | void 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 | ||||
3079 | void 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 | ||||
3115 | void 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 | ||||
3218 | void 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 | ||||
3261 | namespace | |||
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 | ||||
3285 | ErrCode 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 | ||||
3373 | bool 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 | ||||
3420 | ErrCode 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 | ||||
3613 | void 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 | ||||
3671 | ErrCode 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 | } | |||
3771 | ErrCode 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 | ||||
3803 | ErrCode SwWW8Writer::WriteMedium( SfxMedium& ) | |||
3804 | { | |||
3805 | return WriteStorage(); | |||
| ||||
3806 | } | |||
3807 | ||||
3808 | ErrCode 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 | ||||
3817 | MSWordExportBase::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 | ||||
3878 | MSWordExportBase::~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 | ||||
3892 | WW8Export::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 | ||||
3904 | WW8Export::~WW8Export() | |||
3905 | { | |||
3906 | } | |||
3907 | ||||
3908 | AttributeOutputBase& WW8Export::AttrOutput() const | |||
3909 | { | |||
3910 | return *m_pAttrOutput; | |||
3911 | } | |||
3912 | ||||
3913 | MSWordSections& WW8Export::Sections() const | |||
3914 | { | |||
3915 | return *pSepx; | |||
3916 | } | |||
3917 | ||||
3918 | SwWW8Writer::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 | ||||
3928 | SwWW8Writer::~SwWW8Writer() | |||
3929 | { | |||
3930 | } | |||
3931 | ||||
3932 | extern "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 | ||||
3938 | extern "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 | ||||
3943 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) sal_uInt32 GetSaveWarningOfMSVBAStorage_ww8( SfxObjectShell &rDocS ) | |||
3944 | { | |||
3945 | return sal_uInt32(SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( rDocS )); | |||
3946 | } | |||
3947 | ||||
3948 | bool 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 | ||||
3967 | void 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 | ||||
3983 | bool 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 | ||||
3992 | void 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 | ||||
3999 | void 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 | ||||
4015 | void 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 | ||||
4045 | void WW8SHDLong::Write( WW8Export& rExport ) | |||
4046 | { | |||
4047 | rExport.InsUInt32( m_cvFore ); | |||
4048 | rExport.InsUInt32( m_cvBack ); | |||
4049 | rExport.InsUInt16( 0 ); // ipat | |||
4050 | } | |||
4051 | ||||
4052 | void 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 | ||||
4297 | void WW8Export::WriteHyperlinkData( const sw::mark::IFieldmark& /*rFieldmark*/ ) | |||
4298 | { | |||
4299 | //@TODO implement me !!! | |||
4300 | } | |||
4301 | ||||
4302 | void 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 | ||||
4385 | void 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 | ||||
4410 | void 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 | ||||
4433 | const 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: */ |