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