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