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