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 a EditEngine text, then the WhichIds are greater as
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 a EditEngine text, then the WhichIds are greater as
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  SwPaM* 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  delete m_pCurPam; // delete Pam
1854  m_pCurPam = pOldPam;
1855  m_nCurStart = nOldStart;
1856  m_nCurEnd = nOldEnd;
1857  m_pOrigPam = pOldEnd;
1858  m_nTextTyp = nOldTyp;
1859 }
1860 
1861 void WW8Export::OutSwString(const OUString& rStr, sal_Int32 nStt,
1862  sal_Int32 const nLen)
1863 
1864 {
1865  SAL_INFO( "sw.ww8.level2", "<OutSwString>" );
1866 
1867  if( nLen )
1868  {
1869  if( nStt || nLen != rStr.getLength() )
1870  {
1871  OUString sOut( rStr.copy( nStt, nLen ) );
1872 
1873  SAL_INFO( "sw.ww8.level2", sOut );
1874 
1875  SwWW8Writer::WriteString16(Strm(), sOut, false);
1876  }
1877  else
1878  {
1879  SAL_INFO( "sw.ww8.level2", rStr );
1880 
1881  SwWW8Writer::WriteString16(Strm(), rStr, false);
1882  }
1883  }
1884 
1885  SAL_INFO( "sw.ww8.level2", "</OutSwString>" );
1886 }
1887 
1889 {
1890  if (pTableTextNodeInfoInner.get() != nullptr && pTableTextNodeInfoInner->getDepth() == 1 && pTableTextNodeInfoInner->isEndOfCell())
1891  WriteChar('\007');
1892  else
1893  WriteChar( '\015' );
1894 
1896 }
1897 
1899 {
1900  Strm().WriteUInt16( c );
1901 }
1902 
1904 {
1905  m_nCurStart = nStt;
1906  m_nCurEnd = nEnd;
1907  m_pCurPam = Writer::NewSwPaM( *m_pDoc, nStt, nEnd );
1908 
1909  // Recognize tables in special cases
1910  if ( nStt != m_pCurPam->GetMark()->nNode.GetIndex() &&
1911  m_pDoc->GetNodes()[ nStt ]->IsTableNode() )
1912  {
1913  m_pCurPam->GetMark()->nNode = nStt;
1914  }
1915 
1917  m_pCurPam->Exchange();
1918 }
1919 
1921 {
1923 
1924  // WW8Export only stuff - zeroed here not to issue warnings
1925  aData.pOOld = nullptr;
1926 
1927  // Common stuff
1928  aData.pOldPam = m_pCurPam;
1929  aData.pOldEnd = m_pOrigPam;
1930  aData.pOldFlyFormat = m_pParentFrame;
1932 
1933  aData.pOldFlyOffset = m_pFlyOffset;
1935 
1936  aData.bOldOutTable = m_bOutTable;
1938  aData.bOldStartTOX = m_bStartTOX;
1939  aData.bOldInWriteTOX = m_bInWriteTOX;
1940 
1941  SetCurPam(nStt, nEnd);
1942 
1943  m_bOutTable = false;
1944  // Caution: bIsInTable should not be set here
1945  m_bOutFlyFrameAttrs = false;
1946  m_bStartTOX = false;
1947  m_bInWriteTOX = false;
1948 
1949  m_aSaveData.push( std::move(aData) );
1950 }
1951 
1953 {
1954  MSWordSaveData &rData = m_aSaveData.top();
1955 
1956  delete m_pCurPam;
1957  m_pCurPam = rData.pOldPam;
1958  m_nCurStart = rData.nOldStart;
1959  m_nCurEnd = rData.nOldEnd;
1960  m_pOrigPam = rData.pOldEnd;
1961 
1962  m_bOutTable = rData.bOldOutTable;
1964  m_bStartTOX = rData.bOldStartTOX;
1965  m_bInWriteTOX = rData.bOldInWriteTOX;
1966 
1967  m_pParentFrame = rData.pOldFlyFormat;
1969 
1971  m_pFlyOffset = rData.pOldFlyOffset;
1972 
1973  m_aSaveData.pop();
1974 }
1975 
1977 {
1978  MSWordExportBase::SaveData( nStt, nEnd );
1979 
1980  MSWordSaveData &rData = m_aSaveData.top();
1981 
1982  if ( !pO->empty() )
1983  {
1984  rData.pOOld = std::move(pO);
1985  pO.reset(new ww::bytes);
1986  }
1987  else
1988  rData.pOOld = nullptr; // reuse pO
1989 
1991  GetWriter().m_bWriteAll = true;
1992 }
1993 
1995 {
1996  MSWordSaveData &rData = m_aSaveData.top();
1997 
1999 
2000  OSL_ENSURE( pO->empty(), "pO is not empty in WW8Export::RestoreData()" );
2001  if ( rData.pOOld )
2002  {
2003  pO = std::move(rData.pOOld);
2004  }
2005 
2007 }
2008 
2010 {
2011  sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
2012 
2013  if ( nDepth > 0 )
2014  {
2015  /* Cell */
2017  m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2019  m_rWW8Export.InsUInt32( nDepth );
2020 
2021  if ( nDepth > 1 && pTableTextNodeInfoInner->isEndOfCell() )
2022  {
2024  m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2025  }
2026  }
2027 }
2028 
2030 {
2031  sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
2032 
2033  if ( nDepth > 0 )
2034  {
2035  /* Row */
2036  if ( pTableTextNodeInfoInner->isEndOfLine() )
2037  {
2039  m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2040 
2041  if ( nDepth == 1 )
2042  {
2044  m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2045  }
2046 
2048  m_rWW8Export.InsUInt32( nDepth );
2049 
2050  if ( nDepth > 1 )
2051  {
2053  m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2055  m_rWW8Export.pO->push_back( sal_uInt8(0x1) );
2056  }
2057 
2058  TableDefinition( pTableTextNodeInfoInner );
2059  TableHeight( pTableTextNodeInfoInner );
2060  TableBackgrounds( pTableTextNodeInfoInner );
2061  TableDefaultBorders( pTableTextNodeInfoInner );
2062  TableCanSplit( pTableTextNodeInfoInner );
2063  TableBidi( pTableTextNodeInfoInner );
2064  TableVerticalCell( pTableTextNodeInfoInner );
2065  TableOrientation( pTableTextNodeInfoInner );
2066  TableSpacing( pTableTextNodeInfoInner );
2067  TableCellBorders( pTableTextNodeInfoInner );
2068  }
2069  }
2070 }
2071 
2072 static sal_uInt16 lcl_TCFlags(SwDoc &rDoc, const SwTableBox * pBox, sal_Int32 nRowSpan)
2073 {
2074  sal_uInt16 nFlags = 0;
2075 
2076  if (nRowSpan > 1)
2077  nFlags |= (3 << 5);
2078  else if (nRowSpan < 0)
2079  nFlags |= (1 << 5);
2080 
2081  if (pBox != nullptr)
2082  {
2083  const SwFrameFormat * pFormat = pBox->GetFrameFormat();
2084  switch (pFormat->GetVertOrient().GetVertOrient())
2085  {
2086  case text::VertOrientation::CENTER:
2087  nFlags |= (1 << 7);
2088  break;
2090  nFlags |= (2 << 7);
2091  break;
2092  default:
2093  break;
2094  }
2095  const SwStartNode * pSttNd = pBox->GetSttNd();
2096  if(pSttNd)
2097  {
2098  SwNodeIndex aIdx( *pSttNd );
2099  const SwContentNode * pCNd = pSttNd->GetNodes().GoNext( &aIdx );
2100  if( pCNd && pCNd->IsTextNode())
2101  {
2103  static_cast<const SwTextNode*>(pCNd)->GetParaAttr(aCoreSet,
2104  0, static_cast<const SwTextNode*>(pCNd)->GetText().getLength());
2105  const SfxPoolItem * pRotItem;
2106  if ( SfxItemState::SET == aCoreSet.GetItemState(RES_CHRATR_ROTATE, true, &pRotItem))
2107  {
2108  const SvxCharRotateItem * pRotate = static_cast<const SvxCharRotateItem*>(pRotItem);
2109  if(pRotate && pRotate->GetValue() == 900)
2110  {
2111  nFlags = nFlags | 0x0004 | 0x0008;
2112  }
2113  else if(pRotate && pRotate->GetValue() == 2700 )
2114  {
2115  nFlags = nFlags | 0x0004 | 0x0010;
2116  }
2117  }
2118  }
2119  }
2120  }
2121 
2122  return nFlags;
2123 }
2124 
2126 {
2127  const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2128  const SwTableLine * pTabLine = pTabBox->GetUpper();
2129  const SwTableBoxes & rTableBoxes = pTabLine->GetTabBoxes();
2130 
2131  sal_uInt8 nBoxes = rTableBoxes.size();
2132  for ( sal_uInt8 n = 0; n < nBoxes; n++ )
2133  {
2134  const SwTableBox * pTabBox1 = rTableBoxes[n];
2135  const SwFrameFormat * pFrameFormat = pTabBox1->GetFrameFormat();
2136 
2137  // Map from our SvxFrameDirection to WW8 TextFlow.
2138  sal_uInt16 nTextFlow = 0;
2139  switch (m_rWW8Export.TrueFrameDirection(*pFrameFormat))
2140  {
2141  case SvxFrameDirection::Vertical_RL_TB:
2142  nTextFlow = 5;
2143  break;
2144  case SvxFrameDirection::Vertical_LR_BT:
2145  nTextFlow = 3;
2146  break;
2147  default:
2148  break;
2149  }
2150 
2151  if (nTextFlow != 0)
2152  {
2154  m_rWW8Export.pO->push_back( n ); //start range
2155  m_rWW8Export.pO->push_back( sal_uInt8(n + 1) ); //end range
2156  m_rWW8Export.InsUInt16(nTextFlow);
2157  }
2158  }
2159 }
2160 
2162 {
2163  const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2164  const SwTableLine * pTabLine = pTabBox->GetUpper();
2165  const SwFrameFormat * pLineFormat = pTabLine->GetFrameFormat();
2166 
2167  /*
2168  By default the row can be split in word, and now in writer we have a
2169  feature equivalent to this, Word stores 1 for fCantSplit if the row
2170  cannot be split, we set true if we can split it. An example is #i4569#
2171  */
2172 
2173  const SwFormatRowSplit& rSplittable = pLineFormat->GetRowSplit();
2174  sal_uInt8 nCantSplit = (!rSplittable.GetValue()) ? 1 : 0;
2176  m_rWW8Export.pO->push_back( nCantSplit );
2177  m_rWW8Export.InsUInt16( NS_sprm::sprmTFCantSplit90 ); // also write fCantSplit90
2178  m_rWW8Export.pO->push_back( nCantSplit );
2179 }
2180 
2182 {
2183  const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2184  const SwFrameFormat * pFrameFormat = pTable->GetFrameFormat();
2185 
2186  if ( m_rWW8Export.TrueFrameDirection(*pFrameFormat) == SvxFrameDirection::Horizontal_RL_TB )
2187  {
2189  m_rWW8Export.InsUInt16( 1 );
2190  }
2191 }
2192 
2194 {
2195 }
2196 
2198 {
2199 }
2200 
2202 {
2203  const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2204  const SwTableLine * pTabLine = pTabBox->GetUpper();
2205  const SwFrameFormat * pLineFormat = pTabLine->GetFrameFormat();
2206 
2207  // output line height sprmTDyaRowHeight
2208  long nHeight = 0;
2209  const SwFormatFrameSize& rLSz = pLineFormat->GetFrameSize();
2210  if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
2211  {
2212  if ( ATT_MIN_SIZE == rLSz.GetHeightSizeType() )
2213  nHeight = rLSz.GetHeight();
2214  else
2215  nHeight = -rLSz.GetHeight();
2216  }
2217 
2218  if ( nHeight )
2219  {
2221  m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(nHeight) );
2222  }
2223 
2224 }
2225 
2227 {
2228  const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2229 
2230  const SwFrameFormat *pFormat = pTable->GetFrameFormat();
2231  if ( !pFormat )
2232  {
2233  SAL_WARN( "sw.ww8", "FrameFormat is nil" );
2234  return;
2235  }
2236 
2237  const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient();
2238  const SwFormatVertOrient &rVert = pFormat->GetVertOrient();
2239 
2240  if (
2241  (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2242  text::RelOrientation::FRAME == rHori.GetRelationOrient())
2243  &&
2244  (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2245  text::RelOrientation::FRAME == rVert.GetRelationOrient())
2246  )
2247  {
2248  const bool bIsRTL = m_rWW8Export.TrueFrameDirection(*pFormat) == SvxFrameDirection::Horizontal_RL_TB;
2249  sal_Int16 eHOri = rHori.GetHoriOrient();
2250  switch (eHOri)
2251  {
2252  case text::HoriOrientation::CENTER:
2253  m_rWW8Export.InsUInt16( NS_sprm::sprmTJc ); //logical orientation required for MSO
2254  m_rWW8Export.InsUInt16( 1 );
2255  m_rWW8Export.InsUInt16( NS_sprm::sprmTJc90 ); //physical orientation required for LO
2256  m_rWW8Export.InsUInt16( 1 );
2257  break;
2259  m_rWW8Export.InsUInt16( NS_sprm::sprmTJc90 ); //required for LO
2260  m_rWW8Export.InsUInt16( 2 );
2261  if ( !bIsRTL )
2262  {
2263  m_rWW8Export.InsUInt16( NS_sprm::sprmTJc ); //required for MSO
2264  m_rWW8Export.InsUInt16( 2 );
2265  }
2266  break;
2268  if ( bIsRTL )
2269  {
2270  m_rWW8Export.InsUInt16( NS_sprm::sprmTJc ); //required for MSO
2271  m_rWW8Export.InsUInt16( 2 );
2272  }
2273  break;
2274  case text::HoriOrientation::LEFT_AND_WIDTH:
2275  // Width can only be specified for the LOGICAL left, so in RTL, that is always PHYSICAL right
2276  if ( bIsRTL )
2277  {
2278  m_rWW8Export.InsUInt16( NS_sprm::sprmTJc90 ); //required for LO
2279  m_rWW8Export.InsUInt16( 2 );
2280  }
2281  break;
2282  default:
2283  break;
2284  }
2285  }
2286 }
2287 
2289 {
2290  const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2291  const SwTableFormat* pTableFormat = pTable->GetFrameFormat();
2292 
2293 
2294  // Writing these SPRM's will make the table a floating one, so only write
2295  // them in case the table is already inside a frame.
2296  if (pTableFormat != nullptr && pTable->GetTableNode()->GetFlyFormat())
2297  {
2298  const SvxULSpaceItem & rUL = pTableFormat->GetULSpace();
2299 
2300  if (rUL.GetUpper() > 0)
2301  {
2302  sal_uInt8 const nPadding = 2;
2303  sal_uInt8 const nPcVert = 0;
2304  sal_uInt8 const nPcHorz = 0;
2305 
2306  sal_uInt8 const nTPc = (nPadding << 4) | (nPcVert << 2) | nPcHorz;
2307 
2309  m_rWW8Export.pO->push_back( nTPc );
2310 
2313 
2316  }
2317 
2318  if (rUL.GetLower() > 0)
2319  {
2322  }
2323  }
2324 }
2325 
2327 {
2328  const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2329 
2330  if ( pTable->GetRowsToRepeat() > pTableTextNodeInfoInner->getRow() )
2331  {
2333  m_rWW8Export.pO->push_back( 1 );
2334  }
2335 
2336  ww8::TableBoxVectorPtr pTableBoxes =
2337  pTableTextNodeInfoInner->getTableBoxesOfRow();
2338  // number of cell written
2339  sal_uInt32 nBoxes = pTableBoxes->size();
2340  assert(nBoxes <= ww8::MAXTABLECELLS);
2341 
2342  // sprm header
2344  sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
2345  m_rWW8Export.InsUInt16( nSprmSize ); // length
2346 
2347  // number of boxes
2348  m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(nBoxes) );
2349 
2350  /* cells */
2351  /*
2352  ALWAYS relative when text::HoriOrientation::NONE (nPageSize + ( nPageSize / 10 )) < nTableSz,
2353  in that case the cell width's and table width's are not real. The table
2354  width is maxed and cells relative, so we need the frame (generally page)
2355  width that the table is in to work out the true widths.
2356  */
2357  //const bool bNewTableModel = pTable->IsNewModel();
2358  const SwFrameFormat *pFormat = pTable->GetFrameFormat();
2359  if ( !pFormat )
2360  {
2361  SAL_WARN( "sw.ww8", "FrameFormat is nil" );
2362  return;
2363  }
2364 
2365  const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient();
2366  const SwFormatVertOrient &rVert = pFormat->GetVertOrient();
2367 
2368  SwTwips nTableOffset = 0;
2369 
2370  if (
2371  (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
2372  text::RelOrientation::FRAME == rHori.GetRelationOrient())
2373  &&
2374  (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
2375  text::RelOrientation::FRAME == rVert.GetRelationOrient())
2376  )
2377  {
2378  sal_Int16 eHOri = rHori.GetHoriOrient();
2379  switch ( eHOri )
2380  {
2381  case text::HoriOrientation::CENTER:
2383  break;
2384 
2385  default:
2386  nTableOffset = rHori.GetPos();
2387  const SvxLRSpaceItem& rLRSp = pFormat->GetLRSpace();
2388  nTableOffset += rLRSp.GetLeft();
2389 
2390  // convert offset to be measured from right margin in right-to-left tables
2391  if ( nTableOffset && m_rWW8Export.TrueFrameDirection(*pFormat) == SvxFrameDirection::Horizontal_RL_TB )
2392  {
2393  SwTwips nLeftPageMargin, nRightPageMargin;
2394  const SwTwips nPageSize = m_rWW8Export.CurrentPageWidth(nLeftPageMargin, nRightPageMargin);
2395  const SwTwips nTableWidth = pFormat->GetFrameSize().GetWidth();
2396  nTableOffset = nPageSize - nLeftPageMargin - nRightPageMargin - nTableWidth - nTableOffset;
2397  }
2398  break;
2399  }
2400  }
2401 
2402  m_rWW8Export.InsInt16( nTableOffset );
2403 
2404  ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
2405  for ( const auto nCol : *pGridCols )
2406  {
2407  m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(nCol) + nTableOffset );
2408  }
2409 
2410  /* TCs */
2411  ww8::RowSpansPtr pRowSpans = pTableTextNodeInfoInner->getRowSpansOfRow();
2412  ww8::RowSpans::const_iterator aItRowSpans = pRowSpans->begin();
2413 
2414  for (const SwTableBox * pTabBox1 : *pTableBoxes)
2415  {
2416  sal_uInt16 npOCount = m_rWW8Export.pO->size();
2417 
2418  const SwFrameFormat * pBoxFormat = nullptr;
2419  if (pTabBox1 != nullptr)
2420  pBoxFormat = pTabBox1->GetFrameFormat();
2421 
2422  sal_uInt16 nFlags =
2423  lcl_TCFlags(*m_rWW8Export.m_pDoc, pTabBox1, *aItRowSpans);
2424  m_rWW8Export.InsUInt16( nFlags );
2425 
2426  static sal_uInt8 aNullBytes[] = { 0x0, 0x0 };
2427 
2428  m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), aNullBytes, aNullBytes+2 ); // dummy
2429  if (pBoxFormat != nullptr)
2430  {
2431  const SvxBoxItem & rBoxItem = pBoxFormat->GetBox();
2432 
2433  WW8Export::Out_SwFormatTableBox( *m_rWW8Export.pO, &rBoxItem ); // 8/16 Byte
2434  }
2435  else
2436  WW8Export::Out_SwFormatTableBox( *m_rWW8Export.pO, nullptr); // 8/16 Byte
2437 
2438  SAL_INFO( "sw.ww8.level2", "<tclength>" << ( m_rWW8Export.pO->size() - npOCount ) << "</tclength>" );
2439  ++aItRowSpans;
2440  }
2441 
2442  int nWidthPercent = pFormat->GetFrameSize().GetWidthPercent();
2443  // Width is in fiftieths of a percent. For sprmTTableWidth, must be non-negative and 600% max
2444  if ( nWidthPercent > 0 && nWidthPercent <= 600 )
2445  {
2447  m_rWW8Export.pO->push_back( sal_uInt8/*ftsPercent*/ (2) );
2448  m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(nWidthPercent) * 50 );
2449  }
2450 }
2451 
2453 {
2454  return pTableTextNodeInfoInner->getGridColsOfRow(*this);
2455 }
2456 
2458 {
2459  // Get the column widths based on ALL the rows, not just the current row
2460  return pTableTextNodeInfoInner->getGridColsOfRow(*this, true);
2461 }
2462 
2463 void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner const * pTableTextNodeInfoInner, long& rPageSize, bool& rRelBoxSize )
2464 {
2465  long nPageSize = 0;
2466 
2467  const SwNode *pTextNd = pTableTextNodeInfoInner->getNode( );
2468  const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
2469 
2470  const SwFrameFormat *pFormat = pTable->GetFrameFormat();
2471  if ( !pFormat )
2472  {
2473  SAL_WARN( "sw.ww8", "FrameFormat is nil" );
2474  return;
2475  }
2476 
2477  const SwFormatFrameSize &rSize = pFormat->GetFrameSize();
2478  int nWidthPercent = rSize.GetWidthPercent();
2479  bool bManualAligned = pFormat->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::NONE;
2480  if ( (pFormat->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::FULL) || bManualAligned )
2481  nWidthPercent = 100;
2482  bool bRelBoxSize = nWidthPercent != 0;
2483  unsigned long nTableSz = static_cast<unsigned long>(rSize.GetWidth());
2484  if (nTableSz > USHRT_MAX/2 && !bRelBoxSize)
2485  {
2486  OSL_ENSURE(bRelBoxSize, "huge table width but not relative, suspicious");
2487  bRelBoxSize = true;
2488  }
2489 
2490  if ( bRelBoxSize )
2491  {
2492  Point aPt;
2493  SwRect aRect( pFormat->FindLayoutRect( false, &aPt ) );
2494  if ( aRect.IsEmpty() )
2495  {
2496  // Then fetch the page width without margins!
2497  const SwFrameFormat* pParentFormat =
2500  GetExport().m_pDoc->GetPageDesc(0).GetPageFormatOfNode(*pTextNd, false);
2501  aRect = pParentFormat->FindLayoutRect(true);
2502  if ( 0 == ( nPageSize = aRect.Width() ) )
2503  {
2504  const SvxLRSpaceItem& rLR = pParentFormat->GetLRSpace();
2505  nPageSize = pParentFormat->GetFrameSize().GetWidth() - rLR.GetLeft()
2506  - rLR.GetRight();
2507  }
2508  }
2509  else
2510  {
2511  nPageSize = aRect.Width();
2512  if ( bManualAligned )
2513  {
2514  // #i37571# For manually aligned tables
2515  const SvxLRSpaceItem &rLR = pFormat->GetLRSpace();
2516  nPageSize -= (rLR.GetLeft() + rLR.GetRight());
2517  }
2518 
2519  }
2520 
2521  if ( nWidthPercent )
2522  {
2523  nPageSize *= nWidthPercent;
2524  nPageSize /= 100;
2525  }
2526  else
2527  SAL_WARN( "sw.ww8", "nWidthPercent is zero" );
2528  }
2529  else
2530  {
2531  // As the table width is not relative, the TablePageSize equals its width
2532  nPageSize = nTableSz;
2533  }
2534 
2535  rPageSize = nPageSize;
2536  rRelBoxSize = bRelBoxSize;
2537 }
2538 
2540 {
2541  const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2542  const SwFrameFormat * pFrameFormat = pTabBox->GetFrameFormat();
2543 
2544  //Set Default, just taken from the first cell of the first
2545  //row
2546  static const SvxBoxItemLine aBorders[] =
2547  {
2548  SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT,
2549  SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT
2550  };
2551 
2552  for ( int i = 0; i < 4; ++i )
2553  {
2555  m_rWW8Export.pO->push_back( sal_uInt8(6) );
2556  m_rWW8Export.pO->push_back( sal_uInt8(0) );
2557  m_rWW8Export.pO->push_back( sal_uInt8(1) );
2558  m_rWW8Export.pO->push_back( sal_uInt8(1 << i) );
2559  m_rWW8Export.pO->push_back( sal_uInt8(3) );
2560 
2562  pFrameFormat->GetBox().GetDistance( aBorders[i] ) );
2563  }
2564 }
2565 
2567  ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner )
2568 {
2569  const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2570  const SwTableLine * pTabLine = pTabBox->GetUpper();
2571  const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2572  sal_uInt8 nBoxes = std::min<size_t>(rTabBoxes.size(), 255);
2573  const SvxBoxItem * pLastBox = nullptr;
2574  sal_uInt8 nSeqStart = 0; // start of sequence of cells with same borders
2575 
2576  // Detect sequences of cells which have the same borders, and output
2577  // a border description for each such cell range.
2578  for ( unsigned n = 0; n <= nBoxes; ++n )
2579  {
2580  const SvxBoxItem * pBox = (n == nBoxes) ? nullptr :
2581  &rTabBoxes[n]->GetFrameFormat()->GetBox();
2582  if( !pLastBox )
2583  pLastBox = pBox;
2584  else if( !pBox || *pLastBox != *pBox )
2585  {
2586  // This cell has different borders than the previous cell,
2587  // so output the borders for the preceding cell range.
2588  m_rWW8Export.Out_CellRangeBorders(pLastBox, nSeqStart, n);
2589  nSeqStart = n;
2590  pLastBox = pBox;
2591  }
2592  }
2593 }
2594 
2596 {
2597  const SwTable * pTab = pTableTextNodeInfoInner->getTable();
2598  const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2599  const SwTableLine * pTabLine = pTabBox->GetUpper();
2600  const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
2601 
2602  sal_uInt8 nBoxes = rTabBoxes.size();
2604  m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(nBoxes * 2) ); // Len
2605 
2606  Color aRowColor = COL_AUTO;
2607  const SvxBrushItem *pTableColorProp = pTab->GetFrameFormat()->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2608  if ( pTableColorProp )
2609  aRowColor = pTableColorProp->GetColor();
2610 
2611  const SvxBrushItem *pRowColorProp = pTabLine->GetFrameFormat()->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2612  if ( pRowColorProp && pRowColorProp->GetColor() != COL_AUTO )
2613  aRowColor = pRowColorProp->GetColor();
2614 
2615  for ( sal_uInt8 n = 0; n < nBoxes; n++ )
2616  {
2617  const SwTableBox * pBox1 = rTabBoxes[n];
2618  const SwFrameFormat * pFrameFormat = pBox1->GetFrameFormat();
2619  Color aColor = aRowColor;
2620 
2621  const SvxBrushItem *pCellColorProp = pFrameFormat->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2622  if ( pCellColorProp && pCellColorProp->GetColor() != COL_AUTO )
2623  aColor = pCellColorProp->GetColor();
2624 
2625  WW8_SHD aShd;
2626  WW8Export::TransBrush( aColor, aShd );
2627  m_rWW8Export.InsUInt16( aShd.GetValue() );
2628  }
2629 
2630  sal_uInt32 const aSprmIds[] { NS_sprm::sprmTDefTableShd,
2632  sal_uInt8 nBoxes0 = rTabBoxes.size();
2633  if (nBoxes0 > 21)
2634  nBoxes0 = 21;
2635 
2636  for (sal_uInt32 m : aSprmIds)
2637  {
2638  m_rWW8Export.InsUInt16( m );
2639  m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(nBoxes0 * 10) );
2640 
2641  for ( sal_uInt8 n = 0; n < nBoxes0; n++ )
2642  {
2643  const SwTableBox * pBox1 = rTabBoxes[n];
2644  const SwFrameFormat * pFrameFormat = pBox1->GetFrameFormat();
2645  Color aColor = aRowColor;
2646 
2647  const SvxBrushItem *pCellColorProp = pFrameFormat->GetAttrSet().GetItem<SvxBrushItem>(RES_BACKGROUND);
2648  if ( pCellColorProp && pCellColorProp->GetColor() != COL_AUTO )
2649  aColor = pCellColorProp->GetColor();
2650 
2651  WW8SHDLong aSHD;
2652  aSHD.setCvFore( 0xFF000000 );
2653 
2654  if ( aColor == COL_AUTO )
2655  aSHD.setCvBack( 0xFF000000 );
2656  else
2657  aSHD.setCvBack( wwUtility::RGBToBGR( aColor ) );
2658 
2659  aSHD.Write( m_rWW8Export );
2660  }
2661  }
2662 }
2663 
2665 {
2666  // output page/section breaks
2667  OutputSectionBreaks( rNode.GetpSwAttrSet(), rNode );
2668 }
2669 
2671 {
2672 private:
2675 public:
2676  TrackContentToExport(SwPaM *pCurPam, sal_uLong nCurStart, sal_uLong nCurEnd)
2677  : m_pCurPam(pCurPam)
2678  , m_nStart(nCurStart)
2679  , m_nEnd(nCurEnd)
2680  {
2681  }
2682 
2684  {
2685  bool bSimpleContentRemains = m_pCurPam->GetPoint()->nNode < m_pCurPam->GetMark()->nNode ||
2686  (m_pCurPam->GetPoint()->nNode == m_pCurPam->GetMark()->nNode &&
2687  m_pCurPam->GetPoint()->nContent.GetIndex() <= m_pCurPam->GetMark()->nContent.GetIndex());
2688  if (bSimpleContentRemains)
2689  return true;
2690 
2691  if (!pTableInfo)
2692  return false;
2693 
2694  //An old-school table where one cell may points back to a previous node as the next cell
2695  //so if this node is the last node in the range, we may need to jump back to a previously
2696  //skipped cell to output it in a sane sequence. See ooo47778-3.sxw for one of these
2697  //horrors. So if we are at the end of the selection, but this end point is a table
2698  //cell whose next cell is in the selection allow jumping back to it
2699  const SwNode* pCurrentNode = &m_pCurPam->GetPoint()->nNode.GetNode();
2700  const SwNode* pNextNode = pTableInfo->getNextNode(pCurrentNode);
2701 
2702  if (pNextNode && pCurrentNode != pNextNode)
2703  {
2704  return pNextNode->GetIndex() >= m_nStart &&
2705  pNextNode->GetIndex() < m_nEnd;
2706  }
2707 
2708  return false;
2709  }
2710 };
2711 
2713 {
2715  while (aContentTracking.contentRemainsToExport(m_pTableInfo.get()))
2716  {
2717  SwNode& rNd = m_pCurPam->GetNode();
2718 
2719  // no section breaks exported for Endnotes
2720  if ( rNd.IsTextNode() && m_nTextTyp != TXT_EDN && m_nTextTyp != TXT_FTN )
2721  {
2722  SwSoftPageBreakList breakList;
2723  // if paragraph need to be split than handle section break somewhere
2724  // else.
2725  if( !NeedTextNodeSplit( *rNd.GetTextNode(), breakList) )
2727  }
2728 
2729 
2730  // output the various types of nodes
2731  if ( rNd.IsContentNode() )
2732  {
2733  SwContentNode* pCNd = static_cast<SwContentNode*>(&rNd);
2734 
2735  const SwPageDesc* pTemp = rNd.FindPageDesc();
2736  if ( pTemp )
2737  m_pCurrentPageDesc = pTemp;
2738 
2739  m_pCurPam->GetPoint()->nContent.Assign( pCNd, 0 );
2740  OutputContentNode( *pCNd );
2741  }
2742  else if ( rNd.IsTableNode() )
2743  {
2744  m_pTableInfo->processSwTable( &rNd.GetTableNode()->GetTable() );
2745  }
2746  else if ( rNd.IsSectionNode() && TXT_MAINTEXT == m_nTextTyp )
2748  else if ( TXT_MAINTEXT == m_nTextTyp && rNd.IsEndNode() &&
2750  {
2751  const SwSection& rSect = rNd.StartOfSectionNode()->GetSectionNode()
2752  ->GetSection();
2753  if ( m_bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
2754  m_bStartTOX = false;
2755 
2756  SwNodeIndex aIdx( rNd, 1 );
2757  if ( aIdx.GetNode().IsEndNode() && aIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
2758  ;
2759  else if ( aIdx.GetNode().IsSectionNode() )
2760  ;
2761  else if ( !IsInTable()
2762  && (rSect.GetType() != TOX_CONTENT_SECTION && rSect.GetType() != TOX_HEADER_SECTION )) //No sections in table
2763  {
2764  //#120140# Do not need to insert a page/section break after a section end. Check this case first
2765  bool bNeedExportBreakHere = true;
2766  if ( aIdx.GetNode().IsTextNode() )
2767  {
2768  SwTextNode *pTempNext = aIdx.GetNode().GetTextNode();
2769  if ( pTempNext )
2770  {
2771  const SfxPoolItem * pTempItem = nullptr;
2772  if (pTempNext->GetpSwAttrSet() && SfxItemState::SET == pTempNext->GetpSwAttrSet()->GetItemState(RES_PAGEDESC, false, &pTempItem)
2773  && pTempItem && static_cast<const SwFormatPageDesc*>(pTempItem)->GetRegisteredIn())
2774  {
2775  //Next node has a new page style which means this node is a section end. Do not insert another page/section break here
2776  bNeedExportBreakHere = false;
2777  }
2778  }
2779  }
2780  else
2781  {
2782  /* Do not export Section Break in case DOCX containing MultiColumn and
2783  * aIdx.GetNode().IsTextNode() is False i.e. Text node is NULL.
2784  */
2785  const SwFrameFormat* pPgFormat = rSect.GetFormat();
2786  const SwFormatCol& rCol = pPgFormat->GetCol();
2787  sal_uInt16 nColumnCount = rCol.GetNumCols();
2788  const SwFormatNoBalancedColumns& rNoBalanced = pPgFormat->GetBalancedColumns();
2789  // Prevent the additional section break only for non-balanced columns.
2790  if (nColumnCount > 1 && rNoBalanced.GetValue())
2791  {
2792  bNeedExportBreakHere = false;
2793  }
2794  // No need to create a "fake" section if this is the end of the document,
2795  // except to emulate balanced columns.
2796  else if ( nColumnCount < 2 && aIdx == m_pDoc->GetNodes().GetEndOfContent() )
2797  bNeedExportBreakHere = false;
2798  }
2799 
2800  if (bNeedExportBreakHere) //#120140# End of check
2801  {
2802  ReplaceCr( char(0xc) ); // indicator for Page/Section-Break
2803 
2804  const SwSectionFormat* pParentFormat = rSect.GetFormat()->GetParent();
2805  if ( !pParentFormat )
2806  pParentFormat = reinterpret_cast<SwSectionFormat*>(sal_IntPtr(-1));
2807 
2808  sal_uLong nRstLnNum;
2809  if ( aIdx.GetNode().IsContentNode() )
2810  nRstLnNum = static_cast<SwContentNode&>(aIdx.GetNode()).GetSwAttrSet().
2811  GetLineNumber().GetStartValue();
2812  else
2813  nRstLnNum = 0;
2814 
2815  AppendSection( m_pCurrentPageDesc, pParentFormat, nRstLnNum );
2816  }
2817  else
2818  {
2819  OutputEndNode( *rNd.GetEndNode() );
2820  }
2821  }
2822  }
2823  else if ( rNd.IsStartNode() )
2824  {
2825  OutputStartNode( *rNd.GetStartNode() );
2826  }
2827  else if ( rNd.IsEndNode() )
2828  {
2829  OutputEndNode( *rNd.GetEndNode() );
2830  }
2831 
2832  if ( &rNd == &rNd.GetNodes().GetEndOfContent() )
2833  break;
2834 
2835  const SwNode * pCurrentNode = &m_pCurPam->GetPoint()->nNode.GetNode();
2836  const SwNode * pNextNode = m_pTableInfo->getNextNode(pCurrentNode);
2837 
2838  if (pCurrentNode == pNextNode)
2839  {
2840  SAL_WARN("sw.ww8", "loop in TableInfo");
2841  pNextNode = nullptr;
2842  }
2843 
2844  if (pNextNode != nullptr)
2845  m_pCurPam->GetPoint()->nNode.Assign(*pNextNode);
2846  else
2847  ++m_pCurPam->GetPoint()->nNode;
2848 
2851  }
2852 
2853  SAL_INFO( "sw.ww8.level2", "</WriteText>" );
2854 }
2855 
2857 {
2858  SAL_INFO( "sw.ww8.level2", "<WriteMainText>" );
2859 
2860  pFib->m_fcMin = Strm().Tell();
2861 
2863 
2864  WriteText();
2865 
2866  if( 0 == Strm().Tell() - pFib->m_fcMin ) // no text ?
2867  WriteCR(); // then CR at the end ( otherwise WW will complain )
2868 
2869  pFib->m_ccpText = Fc2Cp( Strm().Tell() );
2870  m_pFieldMain->Finish( pFib->m_ccpText, 0 );
2871 
2872  // ccpText includes Footnote and KF-text
2873  // therefore pFib->ccpText may get updated as well
2874  // save the StyleId of the last paragraph. Because WW97 take the style
2875  // from the last CR, that will be written after footer/Header/footnotes/
2876  // annotation etc.
2877  const SwTextNode* pLastNd = m_pCurPam->GetMark()->nNode.GetNode().GetTextNode();
2878  if( pLastNd )
2879  m_nLastFormatId = GetId( static_cast<SwTextFormatColl&>(pLastNd->GetAnyFormatColl()) );
2880 
2881  SAL_INFO( "sw.ww8.level2", "</WriteMainText>" );
2882 }
2883 
2885 {
2886  bool bResult = false;
2887 
2888  if (m_pCurPam != nullptr)
2889  {
2890  SwNode& rNode = m_pCurPam->GetNode();
2891 
2892  if (m_pTableInfo.get() != nullptr)
2893  {
2894  ww8::WW8TableNodeInfo::Pointer_t pTableNodeInfo = m_pTableInfo->getTableNodeInfo(&rNode);
2895 
2896  if (pTableNodeInfo.get() != nullptr && pTableNodeInfo->getDepth() > 0)
2897  {
2898  bResult = true;
2899  }
2900  }
2901  }
2902 
2903  return bResult;
2904 }
2905 
2907 
2909 {
2910  // Graphics in the data stream
2911  m_pGrf->Write(); // Graphics
2912 
2913  // output into WordDocument stream
2914  m_pChpPlc->WriteFkps(); // Fkp.Chpx
2915  m_pPapPlc->WriteFkps(); // Fkp.Papx
2916  pSepx->WriteSepx( Strm() ); // Sepx
2917 
2918  // output into Table stream
2919  m_pStyles->OutputStylesTable(); // for WW8 StyleTab
2920  pFootnote->WritePlc( *this ); // Footnote-Ref & Text Plc
2921  pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
2922  m_pTextBxs->WritePlc( *this ); // Textbox Text Plc
2923  m_pHFTextBxs->WritePlc( *this ); // Head/Foot-Textbox Text Plc
2924  m_pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
2925 
2926  pSepx->WritePlcSed( *this ); // Slcx.PlcSed
2927  pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
2928 
2929  m_pChpPlc->WritePlc(); // Plcx.Chpx
2930  m_pPapPlc->WritePlc(); // Plcx.Papx
2931 
2932  if( m_pRedlAuthors )
2933  m_pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
2934  m_pFieldMain->Write( *this ); // Fields ( Main Text )
2935  m_pFieldHdFt->Write( *this ); // Fields ( Header/Footer )
2936  m_pFieldFootnote->Write( *this ); // Fields ( FootNotes )
2937  m_pFieldEdn->Write( *this ); // Fields ( EndNotes )
2938  m_pFieldAtn->Write( *this ); // Fields ( Annotations )
2939  m_pFieldTextBxs->Write( *this ); // Fields ( Textboxes )
2940  m_pFieldHFTextBxs->Write( *this ); // Fields ( Head/Foot-Textboxes )
2941 
2942  if (m_pEscher || m_pDoc->ContainsMSVBasic())
2943  {
2944  /*
2945  Every time MS 2000 creates an escher stream there is always
2946  an ObjectPool dir (even if empty). It turns out that if a copy of
2947  MS 2000 is used to open a document that contains escher graphics
2948  exported from StarOffice without this empty dir then *if* that
2949  copy of MS Office has never been used to open a MSOffice document
2950  that has escher graphics (and an ObjectPool dir of course) and
2951  that copy of office has not been used to draw escher graphics then
2952  our exported graphics do not appear. Once you do open a ms
2953  document with escher graphics or draw an escher graphic with that
2954  copy of word, then all documents from staroffice that contain
2955  escher work from then on. Tricky to track down, some sort of late
2956  binding trickery in MS where solely for first time initialization
2957  the existence of an ObjectPool dir is necessary for triggering
2958  some magic.
2959  */
2960  // avoid memory leak #i120098#, the unnamed obj will be released in destructor.
2962  }
2963 
2964  // dggInfo - escher stream
2965  WriteEscher();
2966 
2967  m_pSdrObjs->WritePlc( *this );
2968  m_pHFSdrObjs->WritePlc( *this );
2969  // spamom - office drawing table
2970  // spahdr - header office drawing table
2971 
2972  m_pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
2973  // plcfBkmkf/plcfBkmkl
2974  m_pFactoids->Write(*this);
2975 
2976  WriteNumbering();
2977 
2978  RestoreMacroCmds();
2979 
2980  m_pMagicTable->Write( *this );
2981 
2982  m_pPiece->WritePc( *this ); // Piece-Table
2984 
2985  //Convert OOo asian typography into MS typography structure
2986  ExportDopTypography(pDop->doptypography);
2987 
2988  WriteDop( *this ); // Document-Properties
2989 
2990  // Write SttbfAssoc
2991  WW8SttbAssoc * pSttbfAssoc = dynamic_cast<WW8SttbAssoc *>
2993 
2994  if ( pSttbfAssoc ) // #i106057#
2995  {
2996  std::vector<OUString> aStrings(pSttbfAssoc->getStrings());
2997  WriteAsStringTable(aStrings, pFib->m_fcSttbfAssoc,
2998  pFib->m_lcbSttbfAssoc);
2999  }
3000 
3001  Strm().Seek( 0 );
3002 
3003  // Reclaim stored FIB data from document.
3004  ::ww8::WW8FibData * pFibData = dynamic_cast<ww8::WW8FibData *>
3006 
3007  if ( pFibData )
3008  {
3009  pFib->m_fReadOnlyRecommended =
3010  pFibData->getReadOnlyRecommended();
3011  pFib->m_fWriteReservation =
3012  pFibData->getWriteReservation();
3013  }
3014 
3015  pFib->Write( Strm() ); // FIB
3016 }
3017 
3019 {
3020  bool bNeedsFinalPara = false;
3021  // Start of Text ( overwrite )
3022  SwWW8Writer::FillUntil( Strm(), pFib->m_fcMin );
3023 
3024  WriteMainText(); // main text
3025  sal_uInt8 nSprmsLen;
3026  sal_uInt8 *pLastSprms = m_pPapPlc->CopyLastSprms(nSprmsLen);
3027 
3028  bNeedsFinalPara |= pFootnote->WriteText( *this ); // Footnote-Text
3029  bNeedsFinalPara |= pSepx->WriteKFText( *this ); // K/F-Text
3030  bNeedsFinalPara |= m_pAtn->WriteText( *this ); // Annotation-Text
3031  bNeedsFinalPara |= pEdn->WriteText( *this ); // EndNote-Text
3032 
3033  // create the escher streams
3034  CreateEscher();
3035 
3036  bNeedsFinalPara |= m_pTextBxs->WriteText( *this ); //Textbox Text Plc
3037  bNeedsFinalPara |= m_pHFTextBxs->WriteText( *this );//Head/Foot-Textbox Text Plc
3038 
3039  if (bNeedsFinalPara)
3040  {
3041  WriteCR();
3042  m_pPapPlc->AppendFkpEntry(Strm().Tell(), nSprmsLen, pLastSprms);
3043  }
3044  delete[] pLastSprms;
3045 
3046  pSepx->Finish( Fc2Cp( Strm().Tell() ));// Text + Footnote + HdFt as section end
3047  m_pMagicTable->Finish( Fc2Cp( Strm().Tell() ),0);
3048 
3049  pFib->m_fcMac = Strm().Tell(); // End of all texts
3050 
3051  WriteFkpPlcUsw(); // FKP, PLC, .....
3052 }
3053 
3054 void MSWordExportBase::AddLinkTarget(const OUString& rURL)
3055 {
3056  if( rURL.isEmpty() || rURL[0] != '#' )
3057  return;
3058 
3059  OUString aURL( BookmarkToWriter( rURL.copy( 1 ) ) );
3060  sal_Int32 nPos = aURL.lastIndexOf( cMarkSeparator );
3061 
3062  if( nPos < 2 )
3063  return;
3064 
3065  OUString sCmp = aURL.copy(nPos+1).replaceAll(" ", "");
3066  if( sCmp.isEmpty() )
3067  return;
3068 
3069  sCmp = sCmp.toAsciiLowerCase();
3070 
3071  if( sCmp == "outline" )
3072  {
3073  SwPosition aPos( *m_pCurPam->GetPoint() );
3074  OUString aOutline( BookmarkToWriter(aURL.copy( 0, nPos )) );
3075  // If we can find the outline this bookmark refers to
3076  // save the name of the bookmark and the
3077  // node index number of where it points to
3078  if( m_pDoc->GotoOutline( aPos, aOutline ) )
3079  {
3080  sal_uLong nIdx = aPos.nNode.GetIndex();
3081  aBookmarkPair aImplicitBookmark;
3082  aImplicitBookmark.first = aOutline;
3083  aImplicitBookmark.second = nIdx;
3084  m_aImplicitBookmarks.push_back(aImplicitBookmark);
3085  }
3086  }
3087 }
3088 
3090 {
3091  for (const SfxPoolItem* pItem : rDoc.GetAttrPool().GetItemSurrogates(RES_TXTATR_INETFMT))
3092  {
3093  auto pINetFormat = dynamic_cast<const SwFormatINetFormat*>(pItem);
3094  if (!pINetFormat)
3095  continue;
3096 
3097  const SwTextINetFormat* pTextAttr = pINetFormat->GetTextINetFormat();
3098  if (!pTextAttr)
3099  continue;
3100 
3101  const SwTextNode* pTextNd = pTextAttr->GetpTextNode();
3102  if (!pTextNd)
3103  continue;
3104 
3105  if (!pTextNd->GetNodes().IsDocNodes())
3106  continue;
3107 
3108  AddLinkTarget( pINetFormat->GetValue() );
3109  }
3110 
3111  for (const SfxPoolItem* pItem : rDoc.GetAttrPool().GetItemSurrogates(RES_URL))
3112  {
3113  auto pURL = dynamic_cast<const SwFormatURL*>(pItem);
3114  if (!pURL)
3115  continue;
3116 
3117  AddLinkTarget(pURL->GetURL());
3118  const ImageMap *pIMap = pURL->GetMap();
3119  if (!pIMap)
3120  continue;
3121 
3122  for (size_t i=0; i < pIMap->GetIMapObjectCount(); ++i)
3123  {
3124  const IMapObject* pObj = pIMap->GetIMapObject(i);
3125  if (!pObj)
3126  continue;
3127  AddLinkTarget( pObj->GetURL() );
3128  }
3129  }
3130 }
3131 
3132 namespace
3133 {
3134  const sal_uLong WW_BLOCKSIZE = 0x200;
3135 
3136  ErrCode EncryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
3137  {
3138  sal_uLong nLen = rIn.TellEnd();
3139  rIn.Seek(0);
3140 
3141  sal_uInt8 in[WW_BLOCKSIZE];
3142  for (std::size_t nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
3143  {
3144  std::size_t nBS = std::min(nLen - nI, WW_BLOCKSIZE);
3145  nBS = rIn.ReadBytes(in, nBS);
3146  if (!rCtx.InitCipher(nBlock)) {
3147  return ERRCODE_IO_NOTSUPPORTED;
3148  }
3149  rCtx.Encode(in, nBS, in, nBS);
3150  rOut.WriteBytes(in, nBS);
3151  }
3152  return ERRCODE_NONE;
3153  }
3154 }
3155 
3157 {
3160 
3164  m_bInWriteTOX = false;
3165 
3167 
3168  m_pParentFrame = nullptr;
3169  m_pFlyOffset = nullptr;
3170  m_eNewAnchorType = RndStdIds::FLY_AT_PAGE;
3173  m_pStyAttr = nullptr;
3174  m_pCurrentStyle = nullptr;
3175  m_pOutFormatNode = nullptr;
3176  m_pEscher = nullptr;
3177  m_pRedlAuthors = nullptr;
3178  m_aTOXArr.clear();
3179 
3180  if ( !m_pOLEExp )
3181  {
3182  sal_uInt32 nSvxMSDffOLEConvFlags = 0;
3183  const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
3184  if ( rOpt.IsMath2MathType() )
3185  nSvxMSDffOLEConvFlags |= OLE_STARMATH_2_MATHTYPE;
3186  if ( rOpt.IsWriter2WinWord() )
3187  nSvxMSDffOLEConvFlags |= OLE_STARWRITER_2_WINWORD;
3188  if ( rOpt.IsCalc2Excel() )
3189  nSvxMSDffOLEConvFlags |= OLE_STARCALC_2_EXCEL;
3190  if ( rOpt.IsImpress2PowerPoint() )
3191  nSvxMSDffOLEConvFlags |= OLE_STARIMPRESS_2_POWERPOINT;
3192 
3193  m_pOLEExp.reset(new SvxMSExportOLEObjects( nSvxMSDffOLEConvFlags ));
3194  }
3195 
3196  if ( !m_pOCXExp && m_pDoc->GetDocShell() )
3198 
3199  // #i81405# - Collect anchored objects before changing the redline mode.
3200  m_aFrames = GetFrames( *m_pDoc, bWriteAll? nullptr : m_pOrigPam );
3201 
3203 
3204  SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
3205  m_bOrigShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
3206 
3208  {
3209  //restored to original state by SwWriter::Write
3213  }
3214 
3215  // fix the SwPositions in m_aFrames after SetRedlineFlags
3217 
3220 
3222 
3223  // make unique OrdNums (Z-Order) for all drawing-/fly Objects
3226 
3228 
3229  m_aFrames.clear();
3230 
3231  // park m_pCurPam in a "safe place" now that document is fully exported
3232  // before toggling redline mode to avoid ~SwIndexReg assert e.g. export
3233  // ooo103014-1.odt to .doc
3234  // park m_pOrigPam as well, as needed for exporting abi9915-1.odt to doc
3235  m_pOrigPam->DeleteMark();
3236  *m_pOrigPam->GetPoint() = SwPosition(m_pDoc->GetNodes().GetEndOfContent());
3237  *m_pCurPam = *m_pOrigPam;
3238 
3240 
3241  return err;
3242 }
3243 
3245 {
3246  uno::Sequence< beans::NamedValue > aEncryptionData;
3247 
3248  if ( mpMedium )
3249  {
3250  const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mpMedium->GetItemSet(), SID_ENCRYPTIONDATA, false);
3251  if ( pEncryptionDataItem && ( pEncryptionDataItem->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
3252  {
3253  OSL_ENSURE( false, "Unexpected EncryptionData!" );
3254  aEncryptionData.realloc( 0 );
3255  }
3256 
3257  if ( !aEncryptionData.hasElements() )
3258  {
3259  // try to generate the encryption data based on password
3260  const SfxStringItem* pPasswordItem = SfxItemSet::GetItem<SfxStringItem>(mpMedium->GetItemSet(), SID_PASSWORD, false);
3261  if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() && pPasswordItem->GetValue().getLength() <= 15 )
3262  {
3263  // Generate random number with a seed of time as salt.
3264  rtlRandomPool aRandomPool = rtl_random_createPool ();
3265  sal_uInt8 pDocId[ 16 ];
3266  rtl_random_getBytes( aRandomPool, pDocId, 16 );
3267 
3268  rtl_random_destroyPool( aRandomPool );
3269 
3270  sal_uInt16 aPassword[16];
3271  memset( aPassword, 0, sizeof( aPassword ) );
3272 
3273  const OUString& sPassword(pPasswordItem->GetValue());
3274  for ( sal_Int32 nChar = 0; nChar < sPassword.getLength(); ++nChar )
3275  aPassword[nChar] = sPassword[nChar];
3276 
3277  rCodec.InitKey( aPassword, pDocId );
3278  aEncryptionData = rCodec.GetEncryptionData();
3279 
3280  mpMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
3281  }
3282  }
3283 
3284  if ( aEncryptionData.hasElements() )
3285  mpMedium->GetItemSet()->ClearItem( SID_PASSWORD );
3286  }
3287 
3288  // nonempty encryption data means here that the codec was successfully initialized
3289  return aEncryptionData.hasElements();
3290 }
3291 
3293 {
3294  PrepareStorage();
3295 
3296  pFib.reset(new WW8Fib(8, m_bDot));
3297 
3298  tools::SvRef<SotStorageStream> xWwStrm( GetWriter().GetStorage().OpenSotStream( m_aMainStg ) );
3299  tools::SvRef<SotStorageStream> xTableStrm( xWwStrm ), xDataStrm( xWwStrm );
3300  xWwStrm->SetBufferSize( 32768 );
3301 
3302  pFib->m_fWhichTableStm = true;
3303  xTableStrm = GetWriter().GetStorage().OpenSotStream(SL::a1Table, StreamMode::STD_WRITE);
3304  xDataStrm = GetWriter().GetStorage().OpenSotStream(SL::aData, StreamMode::STD_WRITE);
3305 
3306  xDataStrm->SetBufferSize( 32768 ); // for graphics
3307  xTableStrm->SetBufferSize( 16384 ); // for the Font-/Style-Table, etc.
3308 
3309  xTableStrm->SetEndian( SvStreamEndian::LITTLE );
3310  xDataStrm->SetEndian( SvStreamEndian::LITTLE );
3311 
3312  GetWriter().SetStream( xWwStrm.get() );
3313  pTableStrm = xTableStrm.get();
3314  pDataStrm = xDataStrm.get();
3315 
3316  Strm().SetEndian( SvStreamEndian::LITTLE );
3317 
3318  utl::TempFile aTempMain;
3319  aTempMain.EnableKillingFile();
3320  utl::TempFile aTempTable;
3321  aTempTable.EnableKillingFile();
3322  utl::TempFile aTempData;
3323  aTempData.EnableKillingFile();
3324 
3326  bool bEncrypt = GetWriter().InitStd97CodecUpdateMedium(aCtx);
3327  if ( bEncrypt )
3328  {
3329  GetWriter().SetStream(
3330  aTempMain.GetStream( StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE ) );
3331 
3332  pTableStrm = aTempTable.GetStream( StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE );
3333 
3334  pDataStrm = aTempData.GetStream( StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE );
3335 
3336  sal_uInt8 const aRC4EncryptionHeader[ 52 ] = {0};
3337  pTableStrm->WriteBytes(aRC4EncryptionHeader, 52);
3338  }
3339 
3340  // Default: "Standard"
3341  pSepx.reset(new WW8_WrPlcSepx( *this )); // Sections/headers/footers
3342 
3343  pFootnote.reset(new WW8_WrPlcFootnoteEdn( TXT_FTN )); // Footnotes
3344  pEdn.reset(new WW8_WrPlcFootnoteEdn( TXT_EDN )); // Endnotes
3345  m_pAtn = new WW8_WrPlcAnnotations; // PostIts
3346  m_pFactoids.reset(new WW8_WrtFactoids); // Smart tags.
3349 
3350  m_pSdrObjs = new MainTextPlcDrawObj; // Draw-/Fly-Objects for main text
3351  m_pHFSdrObjs = new HdFtPlcDrawObj; // Draw-/Fly-Objects for header/footer
3352 
3353  m_pBkmks = new WW8_WrtBookmarks; // Bookmarks
3355 
3356  m_pPapPlc.reset(new WW8_WrPlcPn( *this, PAP, pFib->m_fcMin ));
3357  m_pChpPlc.reset(new WW8_WrPlcPn( *this, CHP, pFib->m_fcMin ));
3358  pO.reset(new ww::bytes);
3359  m_pStyles.reset(new MSWordStyles( *this ));
3360  m_pFieldMain.reset(new WW8_WrPlcField( 2, TXT_MAINTEXT ));
3361  m_pFieldHdFt.reset(new WW8_WrPlcField( 2, TXT_HDFT ));
3362  m_pFieldFootnote.reset(new WW8_WrPlcField( 2, TXT_FTN ));
3363  m_pFieldEdn.reset(new WW8_WrPlcField( 2, TXT_EDN ));
3364  m_pFieldAtn.reset(new WW8_WrPlcField( 2, TXT_ATN ));
3365  m_pFieldTextBxs.reset(new WW8_WrPlcField( 2, TXT_TXTBOX ));
3367 
3368  m_pMagicTable.reset(new WW8_WrMagicTable);
3369 
3370  m_pGrf.reset(new SwWW8WrGrf( *this ));
3371  m_pPiece = new WW8_WrPct( pFib->m_fcMin );
3372  pDop.reset(new WW8Dop);
3373 
3374  pDop->fRevMarking = bool( RedlineFlags::On & m_nOrigRedlineFlags );
3375  SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
3376  pDop->fRMView = pLayout == nullptr || !pLayout->IsHideRedlines();
3377  pDop->fRMPrint = pDop->fRMView;
3378 
3379  // set AutoHyphenation flag if found in default para style
3380  const SfxPoolItem* pItem;
3381  SwTextFormatColl* pStdTextFormatColl =
3383  if (pStdTextFormatColl && SfxItemState::SET == pStdTextFormatColl->GetItemState(
3384  RES_PARATR_HYPHENZONE, false, &pItem))
3385  {
3386  pDop->fAutoHyphen = static_cast<const SvxHyphenZoneItem*>(pItem)->IsHyphen();
3387  }
3388 
3389  StoreDoc1();
3390 
3392  if ( bEncrypt )
3393  {
3394  SvStream *pStrmTemp, *pTableStrmTemp, *pDataStrmTemp;
3395  pStrmTemp = xWwStrm.get();
3396  pTableStrmTemp = xTableStrm.get();
3397  pDataStrmTemp = xDataStrm.get();
3398 
3399  if ( pDataStrmTemp && pDataStrmTemp != pStrmTemp) {
3400  err = EncryptRC4(aCtx, *pDataStrm, *pDataStrmTemp);
3401  if (err != ERRCODE_NONE) {
3402  goto done;
3403  }
3404  }
3405 
3406  err = EncryptRC4(aCtx, *pTableStrm, *pTableStrmTemp);
3407  if (err != ERRCODE_NONE) {
3408  goto done;
3409  }
3410 
3411  // Write Unencrypted Header 52 bytes to the start of the table stream
3412  // EncryptionVersionInfo (4 bytes): A Version structure where Version.vMajor MUST be 0x0001, and Version.vMinor MUST be 0x0001.
3413  pTableStrmTemp->Seek( 0 );
3414  pTableStrmTemp->WriteUInt32( 0x10001 ); // nEncType
3415 
3416  sal_uInt8 pDocId[16];
3417  aCtx.GetDocId( pDocId );
3418 
3419  sal_uInt8 pSaltData[16];
3420  sal_uInt8 pSaltDigest[16];
3421  aCtx.GetEncryptKey( pDocId, pSaltData, pSaltDigest );
3422 
3423  pTableStrmTemp->WriteBytes(pDocId, 16);
3424  pTableStrmTemp->WriteBytes(pSaltData, 16);
3425  pTableStrmTemp->WriteBytes(pSaltDigest, 16);
3426 
3427  err = EncryptRC4(aCtx, GetWriter().Strm(), *pStrmTemp);
3428  if (err != ERRCODE_NONE) {
3429  goto done;
3430  }
3431 
3432  // Write Unencrypted Fib 68 bytes to the start of the workdocument stream
3433  pFib->m_fEncrypted = true; // fEncrypted indicates the document is encrypted.
3434  pFib->m_fObfuscated = false; // Must be 0 for RC4.
3435  pFib->m_nHash = 0x34; // encrypt header bytes count of table stream.
3436  pFib->m_nKey = 0; // lkey2 must be 0 for RC4.
3437 
3438  pStrmTemp->Seek( 0 );
3439  pFib->WriteHeader( *pStrmTemp );
3440  done:;
3441  }
3442 
3443  m_pGrf.reset();
3444  m_pMagicTable.reset();;
3445  m_pFieldFootnote.reset();;
3446  m_pFieldTextBxs.reset();;
3447  m_pFieldHFTextBxs.reset();;
3448  m_pFieldAtn.reset();;
3449  m_pFieldEdn.reset();;
3450  m_pFieldHdFt.reset();;
3451  m_pFieldMain.reset();;
3452  m_pStyles.reset();;
3453  pO.reset();
3454  m_pChpPlc.reset();;
3455  m_pPapPlc.reset();;
3456  pSepx.reset();
3457 
3458  delete m_pRedlAuthors;
3459  delete m_pSdrObjs;
3460  delete m_pHFSdrObjs;
3461  delete m_pTextBxs;
3462  delete m_pHFTextBxs;
3463  delete m_pAtn;
3464  pEdn.reset();
3465  pFootnote.reset();
3466  delete m_pBkmks;
3467  delete m_pPiece;
3468  pDop.reset();
3469  pFib.reset();
3470  GetWriter().SetStream( nullptr );
3471 
3472  xWwStrm->SetBufferSize( 0 );
3473  xTableStrm->SetBufferSize( 0 );
3474  xDataStrm->SetBufferSize( 0 );
3475  if( 0 == pDataStrm->Seek( STREAM_SEEK_TO_END ))
3476  {
3477  xDataStrm.clear();
3478  pDataStrm = nullptr;
3480  }
3481 
3482  return err;
3483 }
3484 
3486 {
3487  static const sal_uInt8 pData[] =
3488  {
3489  0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
3490  0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x09, 0x02, 0x00,
3491  0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
3492  0x00, 0x00, 0x00, 0x46,
3493 
3494  0x18, 0x00, 0x00, 0x00,
3495  'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
3496  't', ' ', 'W', 'o', 'r', 'd', '-', 'D',
3497  'o', 'k', 'u', 'm', 'e', 'n', 't', 0x0,
3498 
3499  0x0A, 0x00, 0x00, 0x00,
3500  'M', 'S', 'W', 'o', 'r', 'd', 'D', 'o',
3501  'c', 0x0,
3502 
3503  0x10, 0x00, 0x00, 0x00,
3504  'W', 'o', 'r', 'd', '.', 'D', 'o', 'c',
3505  'u', 'm', 'e', 'n', 't', '.', '8', 0x0,
3506 
3507  0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00,
3508  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3509  };
3510 
3511  SvGlobalName aGName(MSO_WW8_CLASSID);
3513  aGName, SotClipboardFormatId::NONE, "Microsoft Word-Document");
3514  tools::SvRef<SotStorageStream> xStor( GetWriter().GetStorage().OpenSotStream(sCompObj) );
3515  xStor->WriteBytes(pData, sizeof(pData));
3516 
3517  SwDocShell* pDocShell = m_pDoc->GetDocShell ();
3518  OSL_ENSURE(pDocShell, "no SwDocShell");
3519 
3520  if (pDocShell) {
3521  uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3522  pDocShell->GetModel(), uno::UNO_QUERY_THROW);
3523  uno::Reference<document::XDocumentProperties> xDocProps(
3524  xDPS->getDocumentProperties());
3525  OSL_ENSURE(xDocProps.is(), "DocumentProperties is null");
3526 
3527  if (xDocProps.is())
3528  {
3530  {
3531  std::shared_ptr<GDIMetaFile> xMetaFile =
3532  pDocShell->GetPreviewMetaFile();
3533  uno::Sequence<sal_Int8> metaFile(
3534  sfx2::convertMetaFile(xMetaFile.get()));
3535  sfx2::SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
3536  }
3537  else
3538  sfx2::SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
3539  }
3540  }
3541 }
3542 
3544 {
3545  // #i34818# - update layout (if present), for SwWriteTable
3547  if( pViewShell != nullptr )
3548  pViewShell->CalcLayout();
3549 
3550  long nMaxNode = m_pDoc->GetNodes().Count();
3551  ::StartProgress( STR_STATSTR_W4WWRITE, 0, nMaxNode, m_pDoc->GetDocShell() );
3552 
3553  // Respect table at the beginning of the document
3554  {
3556  if( pTNd && m_bWriteAll )
3557  // start with the table node !!
3558  m_pCurrentPam->GetPoint()->nNode = *pTNd;
3559  }
3560 
3561  // Do the actual export
3563  {
3564  bool bDot = mpMedium->GetFilter()->GetName().endsWith("Vorlage");
3565  WW8Export aExport(this, m_pDoc, m_pCurrentPam, m_pOrigPam, bDot);
3566  m_pExport = &aExport;
3567  err = aExport.ExportDocument( m_bWriteAll );
3568  m_pExport = nullptr;
3569  }
3570 
3572  return err;
3573 }
3574 
3576 {
3577  return WriteStorage();
3578 }
3579 
3581  const OUString* pFileName )
3582 {
3583  mpMedium = &rMed;
3584  ErrCode nRet = StgWriter::Write( rPaM, rMed, pFileName );
3585  mpMedium = nullptr;
3586  return nRet;
3587 }
3588 
3589 MSWordExportBase::MSWordExportBase( SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
3590  : m_aMainStg(sMainStream)
3591  , m_pISet(nullptr)
3592  , m_pPiece(nullptr)
3593  , m_pTopNodeOfHdFtPage(nullptr)
3594  , m_pBkmks(nullptr)
3595  , m_pRedlAuthors(nullptr)
3596  , m_pTableInfo(new ww8::WW8TableInfo())
3597  , m_nCharFormatStart(0)
3598  , m_nFormatCollStart(0)
3599  , m_nStyleBeforeFly(0)
3600  , m_nLastFormatId(0)
3601  , m_nUniqueList(0)
3602  , m_nHdFtIndex(0)
3603  , m_nOrigRedlineFlags(RedlineFlags::NONE)
3604  , m_bOrigShowChanges(true)
3605  , m_pCurrentPageDesc(nullptr)
3606  , m_bPrevTextNodeIsEmpty(false)
3607  , m_bFirstTOCNodeWithSection(false)
3608  , m_pChpIter(nullptr)
3609  , m_pAtn(nullptr)
3610  , m_pTextBxs(nullptr)
3611  , m_pHFTextBxs(nullptr)
3612  , m_pParentFrame(nullptr)
3613  , m_pFlyOffset(nullptr)
3614  , m_eNewAnchorType(RndStdIds::FLY_AS_CHAR)
3615  , m_pStyAttr(nullptr)
3616  , m_pOutFormatNode(nullptr)
3617  , m_pCurrentStyle(nullptr)
3618  , m_pSdrObjs(nullptr)
3619  , m_pHFSdrObjs(nullptr)
3620  , m_pEscher(nullptr)
3621  , m_nTextTyp(0)
3622  , m_bStyDef(false)
3623  , m_bBreakBefore(false)
3624  , m_bOutKF(false)
3625  , m_bOutFlyFrameAttrs(false)
3626  , m_bOutPageDescs(false)
3627  , m_bOutFirstPage(false)
3628  , m_bOutTable(false)
3629  , m_bOutGrf(false)
3630  , m_bInWriteEscher(false)
3631  , m_bStartTOX(false)
3632  , m_bInWriteTOX(false)
3633  , m_bFootnoteAtTextEnd(false)
3634  , m_bEndAtTextEnd(false)
3635  , m_bHasHdr(false)
3636  , m_bHasFtr(false)
3637  , m_bSubstituteBullets(true)
3638  , m_bTabInTOC(false)
3639  , m_bHideTabLeaderAndPageNumbers(false)
3640  , m_bExportModeRTF(false)
3641  , m_bFontSizeWritten(false)
3642  , m_bAddFootnoteTab(false)
3643  , m_pDoc(pDocument)
3644  , m_nCurStart(pCurrentPam->GetPoint()->nNode.GetIndex())
3645  , m_nCurEnd(pCurrentPam->GetMark()->nNode.GetIndex())
3646  , m_pCurPam(pCurrentPam)
3647  , m_pOrigPam(pOriginalPam)
3648 {
3649 }
3650 
3652 {
3653  if (m_pUsedNumTable) // all used NumRules
3654  {
3655  // clear the part of the list array that was copied from the document
3656  // - it's an auto delete array, so the rest of the array which are
3657  // duplicated lists that were added during the export will be deleted.
3658  m_pUsedNumTable->erase(m_pUsedNumTable->begin(), m_pUsedNumTable->begin() + m_pUsedNumTable->size() - m_nUniqueList);
3659  m_pUsedNumTable.reset();
3660  }
3661  m_pOLEExp.reset();
3662  m_pOCXExp.reset();
3663 }
3664 
3666  SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam,
3667  bool bDot )
3668  : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam )
3669  , pTableStrm(nullptr)
3670  , pDataStrm(nullptr)
3671  , m_bDot(bDot)
3672  , m_pWriter(pWriter)
3673  , m_pAttrOutput(new WW8AttributeOutput(*this))
3674 {
3675 }
3676 
3678 {
3679 }
3680 
3682 {
3683  return *m_pAttrOutput;
3684 }
3685 
3687 {
3688  return *pSepx;
3689 }
3690 
3691 SwWW8Writer::SwWW8Writer(const OUString& rFltName, const OUString& rBaseURL)
3692  : StgWriter(),
3693  m_pExport( nullptr ),
3694  mpMedium( nullptr )
3695 {
3696  assert(rFltName == FILTER_WW8); // WW6/7 export was removed
3697  (void)rFltName;
3698  SetBaseURL( rBaseURL );
3699 }
3700 
3702 {
3703 }
3704 
3705 extern "C" SAL_DLLPUBLIC_EXPORT sal_uInt32 SaveOrDelMSVBAStorage_ww8( SfxObjectShell& rDoc, SotStorage& rStor, sal_Bool bSaveInto, const OUString& rStorageName )
3706 {
3707  SvxImportMSVBasic aTmp( rDoc, rStor );
3708  return sal_uInt32(aTmp.SaveOrDelMSVBAStorage( bSaveInto, rStorageName ));
3709 }
3710 
3711 extern "C" SAL_DLLPUBLIC_EXPORT void ExportDOC( const OUString& rFltName, const OUString& rBaseURL, WriterRef& xRet )
3712 {
3713  xRet = new SwWW8Writer( rFltName, rBaseURL );
3714 }
3715 
3716 extern "C" SAL_DLLPUBLIC_EXPORT sal_uInt32 GetSaveWarningOfMSVBAStorage_ww8( SfxObjectShell &rDocS )
3717 {
3718  return sal_uInt32(SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( rDocS ));
3719 }
3720 
3722 {
3723  bool bRet = false;
3724  if (TXT_FTN == nTyp)
3725  {
3726  bRet = WriteGenericText( rWrt, TXT_FTN, rWrt.pFib->m_ccpFootnote );
3727  rWrt.m_pFieldFootnote->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3728  rWrt.pFib->m_ccpText );
3729  }
3730  else
3731  {
3732  bRet = WriteGenericText( rWrt, TXT_EDN, rWrt.pFib->m_ccpEdn );
3733  rWrt.m_pFieldEdn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3734  rWrt.pFib->m_ccpText + rWrt.pFib->m_ccpFootnote
3735  + rWrt.pFib->m_ccpHdr + rWrt.pFib->m_ccpAtn );
3736  }
3737  return bRet;
3738 }
3739 
3741 {
3742  if( TXT_FTN == nTyp )
3743  {
3744  WriteGenericPlc( rWrt, TXT_FTN, rWrt.pFib->m_fcPlcffndText,
3745  rWrt.pFib->m_lcbPlcffndText, rWrt.pFib->m_fcPlcffndRef,
3746  rWrt.pFib->m_lcbPlcffndRef );
3747  }
3748  else
3749  {
3750  WriteGenericPlc( rWrt, TXT_EDN, rWrt.pFib->m_fcPlcfendText,
3751  rWrt.pFib->m_lcbPlcfendText, rWrt.pFib->m_fcPlcfendRef,
3752  rWrt.pFib->m_lcbPlcfendRef );
3753  }
3754 }
3755 
3757 {
3758  bool bRet = WriteGenericText( rWrt, TXT_ATN, rWrt.pFib->m_ccpAtn );
3759  rWrt.m_pFieldAtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
3760  rWrt.pFib->m_ccpText + rWrt.pFib->m_ccpFootnote
3761  + rWrt.pFib->m_ccpHdr );
3762  return bRet;
3763 }
3764 
3766 {
3767  WriteGenericPlc( rWrt, TXT_ATN, rWrt.pFib->m_fcPlcfandText,
3768  rWrt.pFib->m_lcbPlcfandText, rWrt.pFib->m_fcPlcfandRef,
3769  rWrt.pFib->m_lcbPlcfandRef );
3770 }
3771 
3773 {
3774  if( TXT_TXTBOX == nTyp )
3775  {
3776  WriteGenericPlc( rWrt, nTyp, rWrt.pFib->m_fcPlcftxbxBkd,
3777  rWrt.pFib->m_lcbPlcftxbxBkd, rWrt.pFib->m_fcPlcftxbxText,
3778  rWrt.pFib->m_lcbPlcftxbxText );
3779  }
3780  else
3781  {
3782  WriteGenericPlc( rWrt, nTyp, rWrt.pFib->m_fcPlcfHdrtxbxBkd,
3783  rWrt.pFib->m_lcbPlcfHdrtxbxBkd, rWrt.pFib->m_fcPlcfHdrtxbxText,
3784  rWrt.pFib->m_lcbPlcfHdrtxbxText );
3785  }
3786 }
3787 
3789 {
3790  pFib->m_fcCmds = pTableStrm->Tell();
3791 
3792  uno::Reference < embed::XStorage > xSrcRoot(m_pDoc->GetDocShell()->GetStorage());
3793  try
3794  {
3795  uno::Reference < io::XStream > xSrcStream =
3796  xSrcRoot->openStreamElement( SL::aMSMacroCmds, embed::ElementModes::READ );
3797  std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( xSrcStream );
3798 
3799  if ( pStream && ERRCODE_NONE == pStream->GetError())
3800  {
3801  pFib->m_lcbCmds = pStream->TellEnd();
3802  pStream->Seek(0);
3803 
3804  std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[pFib->m_lcbCmds] );
3805  bool bReadOk = checkRead(*pStream, pBuffer.get(), pFib->m_lcbCmds);
3806  if (bReadOk)
3807  pTableStrm->WriteBytes(pBuffer.get(), pFib->m_lcbCmds);
3808  }
3809  }
3810  catch ( const uno::Exception& )
3811  {
3812  }
3813 
3814  // set len to FIB
3815  pFib->m_lcbCmds = pTableStrm->Tell() - pFib->m_fcCmds;
3816 }
3817 
3819 {
3820  rExport.InsUInt32( m_cvFore );
3821  rExport.InsUInt32( m_cvBack );
3822  rExport.InsUInt16( 0 ); // ipat
3823 }
3824 
3825 void WW8Export::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
3826 {
3827  const ::sw::mark::IFieldmark* pFieldmark = &rFieldmark;
3828  const ::sw::mark::ICheckboxFieldmark* pAsCheckbox = dynamic_cast< const ::sw::mark::ICheckboxFieldmark* >( pFieldmark );
3829 
3830  if ( ! ( rFieldmark.GetFieldname() == ODF_FORMTEXT ||
3831  rFieldmark.GetFieldname() == ODF_FORMDROPDOWN ||
3832  rFieldmark.GetFieldname() == ODF_FORMCHECKBOX ) )
3833  {
3834  SAL_WARN( "sw.ww8", "unknown field type" );
3835  return;
3836  }
3837 
3838  int type = 0; // TextFieldmark
3839  if ( pAsCheckbox )
3840  type = 1;
3841  if ( rFieldmark.GetFieldname() == ODF_FORMDROPDOWN )
3842  type=2;
3843 
3844  ::sw::mark::IFieldmark::parameter_map_t::const_iterator pParameter = rFieldmark.GetParameters()->find("name");
3845  OUString ffname;
3846  if ( pParameter != rFieldmark.GetParameters()->end() )
3847  {
3848  OUString aName;
3849  pParameter->second >>= aName;
3850  assert( aName.getLength() < 21 && "jluth seeing if following documentation will cause problems." );
3851  const sal_Int32 nLen = std::min( sal_Int32(20), aName.getLength() );
3852  ffname = aName.copy(0, nLen);
3853  }
3854 
3855  sal_uInt64 nDataStt = pDataStrm->Tell();
3856  m_pChpPlc->AppendFkpEntry(Strm().Tell());
3857 
3858  WriteChar(0x01);
3859  static sal_uInt8 aArr1[] =
3860  {
3861  0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
3862 
3863  0x06, 0x08, 0x01, // sprmCFData
3864  0x55, 0x08, 0x01, // sprmCFSpec
3865  0x02, 0x08, 0x01 // sprmCFFieldVanish
3866  };
3867  sal_uInt8* pDataAdr = aArr1 + 2;
3868  Set_UInt32(pDataAdr, nDataStt);
3869 
3870  m_pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aArr1 ), aArr1 );
3871 
3872  struct FFDataHeader
3873  {
3874  sal_uInt32 version;
3875  sal_uInt16 bits;
3876  sal_uInt16 cch;
3877  sal_uInt16 hps;
3878  FFDataHeader() : version( 0xFFFFFFFF ), bits(0), cch(0), hps(0) {}
3879  };
3880 
3881  FFDataHeader aFieldHeader;
3882  aFieldHeader.bits |= (type & 0x03);
3883 
3884  sal_Int32 ffres = 0; // rFieldmark.GetFFRes();
3885  if ( pAsCheckbox && pAsCheckbox->IsChecked() )
3886  ffres = 1;
3887  else if ( type == 2 )
3888  {
3889  ::sw::mark::IFieldmark::parameter_map_t::const_iterator pResParameter = rFieldmark.GetParameters()->find(ODF_FORMDROPDOWN_RESULT);
3890  if(pResParameter != rFieldmark.GetParameters()->end())
3891  pResParameter->second >>= ffres;
3892  else
3893  ffres = 0;
3894  }
3895  aFieldHeader.bits |= ( (ffres<<2) & 0x7C );
3896 
3897  OUString ffdeftext;
3898  OUString ffformat;
3899  OUString ffhelptext = rFieldmark.GetFieldHelptext();
3900  if ( ffhelptext.getLength() > 255 )
3901  ffhelptext = ffhelptext.copy(0, 255);
3902  OUString ffstattext;
3903  OUString ffentrymcr;
3904  OUString ffexitmcr;
3905  if (type == 0) // iTypeText
3906  {
3907  sal_uInt16 nType = 0;
3908  pParameter = rFieldmark.GetParameters()->find("Type");
3909  if ( pParameter != rFieldmark.GetParameters()->end() )
3910  {
3911  OUString aType;
3912  pParameter->second >>= aType;
3913  if ( aType == "number" ) nType = 1;
3914  else if ( aType == "date" ) nType = 2;
3915  else if ( aType == "currentTime" ) nType = 3;
3916  else if ( aType == "currentDate" ) nType = 4;
3917  else if ( aType == "calculated" ) nType = 5;
3918  aFieldHeader.bits |= nType<<11; // FFDataBits-F 00111000 00000000
3919  }
3920 
3921  if ( nType < 3 || nType == 5 ) // not currentTime or currentDate
3922  {
3923  pParameter = rFieldmark.GetParameters()->find("Content");
3924  if ( pParameter != rFieldmark.GetParameters()->end() )
3925  {
3926  OUString aDefaultText;
3927  pParameter->second >>= aDefaultText;
3928  assert( aDefaultText.getLength() < 256 && "jluth seeing if following documentation will cause problems." );
3929  const sal_Int32 nLen = std::min( sal_Int32(255), aDefaultText.getLength() );
3930  ffdeftext = aDefaultText.copy (0, nLen);
3931  }
3932  }
3933 
3934  pParameter = rFieldmark.GetParameters()->find("MaxLength");
3935  if ( pParameter != rFieldmark.GetParameters()->end() )
3936  {
3937  sal_uInt16 nLength = 0;
3938  pParameter->second >>= nLength;
3939  assert( nLength < 32768 && "jluth seeing if following documentation will cause problems." );
3940  nLength = std::min( sal_uInt16(32767), nLength );
3941  aFieldHeader.cch = nLength;
3942  }
3943 
3944  pParameter = rFieldmark.GetParameters()->find("Format");
3945  if ( pParameter != rFieldmark.GetParameters()->end() )
3946  {
3947  OUString aFormat;
3948  pParameter->second >>= aFormat;
3949  const sal_Int32 nLen = std::min( sal_Int32(64), aFormat.getLength() );
3950  assert( nLen < 65 && "jluth seeing if following documentation will cause problems." );
3951  ffformat = aFormat.copy(0, nLen);
3952  }
3953  }
3954 
3955  pParameter = rFieldmark.GetParameters()->find("Help"); //help
3956  if ( ffhelptext.isEmpty() && pParameter != rFieldmark.GetParameters()->end() )
3957  {
3958  OUString aHelpText;
3959  pParameter->second >>= aHelpText;
3960  const sal_Int32 nLen = std::min( sal_Int32(255), aHelpText.getLength() );
3961  ffhelptext = aHelpText.copy (0, nLen);
3962  }
3963  if ( !ffhelptext.isEmpty() )
3964  aFieldHeader.bits |= 0x1<<7;
3965 
3966  pParameter = rFieldmark.GetParameters()->find("Description"); // doc tooltip
3967  if ( pParameter == rFieldmark.GetParameters()->end() )
3968  pParameter = rFieldmark.GetParameters()->find("Hint"); //docx tooltip
3969  if ( pParameter != rFieldmark.GetParameters()->end() )
3970  {
3971  OUString aStatusText;
3972  pParameter->second >>= aStatusText;
3973  const sal_Int32 nLen = std::min( sal_Int32(138), aStatusText.getLength() );
3974  ffstattext = aStatusText.copy (0, nLen);
3975  }
3976  if ( !ffstattext.isEmpty() )
3977  aFieldHeader.bits |= 0x1<<8;
3978 
3979  pParameter = rFieldmark.GetParameters()->find("EntryMacro");
3980  if ( pParameter != rFieldmark.GetParameters()->end() )
3981  {
3982  OUString aEntryMacro;
3983  pParameter->second >>= aEntryMacro;
3984  assert( aEntryMacro.getLength() < 33 && "jluth seeing if following documentation will cause problems." );
3985  const sal_Int32 nLen = std::min( sal_Int32(32), aEntryMacro.getLength() );
3986  ffentrymcr = aEntryMacro.copy (0, nLen);
3987  }
3988 
3989  pParameter = rFieldmark.GetParameters()->find("ExitMacro");
3990  if ( pParameter != rFieldmark.GetParameters()->end() )
3991  {
3992  OUString aExitMacro;
3993  pParameter->second >>= aExitMacro;
3994  assert( aExitMacro.getLength() < 33 && "jluth seeing if following documentation will cause problems." );
3995  const sal_Int32 nLen = std::min( sal_Int32(32), aExitMacro.getLength() );
3996  ffexitmcr = aExitMacro.copy (0, nLen);
3997  }
3998 
3999  std::vector< OUString > aListItems;
4000  if (type==2)
4001  {
4002  aFieldHeader.bits |= 0x8000; // ffhaslistbox
4003  const ::sw::mark::IFieldmark::parameter_map_t* const pParameters = rFieldmark.GetParameters();
4004  ::sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
4005  if(pListEntries != pParameters->end())
4006  {
4007  uno::Sequence< OUString > vListEntries;
4008  pListEntries->second >>= vListEntries;
4009  copy(vListEntries.begin(), vListEntries.end(), back_inserter(aListItems));
4010  }
4011  }
4012 
4013  const sal_uInt8 aFieldData[] =
4014  {
4015  0x44,0, // the start of "next" data
4016  0,0,0,0,0,0,0,0,0,0, // PIC-Structure! /10
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,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
4020  0,0,0,0, // / /4
4021  };
4022  sal_uInt32 slen = sizeof(sal_uInt32)
4023  + sizeof(aFieldData)
4024  + sizeof( aFieldHeader.version ) + sizeof( aFieldHeader.bits ) + sizeof( aFieldHeader.cch ) + sizeof( aFieldHeader.hps )
4025  + 2*ffname.getLength() + 4
4026  + 2*ffformat.getLength() + 4
4027  + 2*ffhelptext.getLength() + 4
4028  + 2*ffstattext.getLength() + 4
4029  + 2*ffentrymcr.getLength() + 4
4030  + 2*ffexitmcr.getLength() + 4;
4031  if ( type )
4032  slen += 2; // wDef
4033  else
4034  slen += 2*ffdeftext.getLength() + 4; //xstzTextDef
4035  if ( type==2 ) {
4036  slen += 2; // sttb ( fExtend )
4037  slen += 4; // for num of list items
4038  const int items = aListItems.size();
4039  for( int i = 0; i < items; i++ ) {
4040  OUString item = aListItems[i];
4041  slen += 2 * item.getLength() + 2;
4042  }
4043  }
4044 
4045  pDataStrm->WriteUInt32( slen );
4046 
4047  int len = sizeof( aFieldData );
4048  OSL_ENSURE( len == 0x44-sizeof(sal_uInt32), "SwWW8Writer::WriteFormData(..) - wrong aFieldData length" );
4049  pDataStrm->WriteBytes( aFieldData, len );
4050 
4051  pDataStrm->WriteUInt32( aFieldHeader.version ).WriteUInt16( aFieldHeader.bits ).WriteUInt16( aFieldHeader.cch ).WriteUInt16( aFieldHeader.hps );
4052 
4053  SwWW8Writer::WriteString_xstz( *pDataStrm, ffname, true ); // Form field name
4054 
4055  if ( !type )
4056  SwWW8Writer::WriteString_xstz( *pDataStrm, ffdeftext, true );
4057  if ( type )
4058  pDataStrm->WriteUInt16( 0 );
4059 
4060  SwWW8Writer::WriteString_xstz( *pDataStrm, ffformat, true );
4061  SwWW8Writer::WriteString_xstz( *pDataStrm, ffhelptext, true );
4062  SwWW8Writer::WriteString_xstz( *pDataStrm, ffstattext, true );
4063  SwWW8Writer::WriteString_xstz( *pDataStrm, ffentrymcr, true );
4064  SwWW8Writer::WriteString_xstz( *pDataStrm, ffexitmcr, true );
4065  if (type==2) {
4066  pDataStrm->WriteUInt16( 0xFFFF );
4067  const int items=aListItems.size();
4068  pDataStrm->WriteUInt32( items );
4069  for(int i=0;i<items;i++) {
4070  OUString item=aListItems[i];
4071  SwWW8Writer::WriteString_xstz( *pDataStrm, item, false );
4072  }
4073  }
4074 }
4075 
4077 {
4078  //@TODO implement me !!!
4079 }
4080 
4082 {
4083  SVBT16 nStyle;
4084  ShortToSVBT16( m_rWW8Export.m_nStyleBeforeFly, nStyle );
4085 
4086 #ifdef DBG_UTIL
4087  SAL_INFO( "sw.ww8", "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner->toString());
4088 #endif
4089 
4090  m_rWW8Export.pO->clear();
4091 
4092  sal_uInt32 nShadowsBefore = pNodeInfoInner->getShadowsBefore();
4093  if (nShadowsBefore > 0)
4094  {
4096  pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(nullptr));
4097 
4098  pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
4099  pTmpNodeInfoInner->setEndOfCell(true);
4100 
4101  for (sal_uInt32 n = 0; n < nShadowsBefore; ++n)
4102  {
4103  m_rWW8Export.WriteCR(pTmpNodeInfoInner);
4104 
4105  m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4106  TableInfoCell(pTmpNodeInfoInner);
4107  m_rWW8Export.m_pPapPlc->AppendFkpEntry
4108  ( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4109 
4110  m_rWW8Export.pO->clear();
4111  }
4112  }
4113 
4114  if (pNodeInfoInner->isEndOfCell())
4115  {
4116  SAL_INFO( "sw.ww8", "<endOfCell/>" );
4117 
4118  m_rWW8Export.WriteCR(pNodeInfoInner);
4119 
4120  m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4121  TableInfoCell(pNodeInfoInner);
4122  m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4123 
4124  m_rWW8Export.pO->clear();
4125  }
4126 
4127  sal_uInt32 nShadowsAfter = pNodeInfoInner->getShadowsAfter();
4128  if (nShadowsAfter > 0)
4129  {
4131  pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(nullptr));
4132 
4133  pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
4134  pTmpNodeInfoInner->setEndOfCell(true);
4135 
4136  for (sal_uInt32 n = 0; n < nShadowsAfter; ++n)
4137  {
4138  m_rWW8Export.WriteCR(pTmpNodeInfoInner);
4139 
4140  m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4141  TableInfoCell(pTmpNodeInfoInner);
4142  m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4143 
4144  m_rWW8Export.pO->clear();
4145  }
4146  }
4147 
4148  if (pNodeInfoInner->isEndOfLine())
4149  {
4150  SAL_INFO( "sw.ww8", "<endOfLine/>" );
4151 
4152  TableRowEnd(pNodeInfoInner->getDepth());
4153 
4154  ShortToSVBT16(0, nStyle);
4155  m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nStyle, nStyle+2 ); // Style #
4156  TableInfoRow(pNodeInfoInner);
4157  m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
4158 
4159  m_rWW8Export.pO->clear();
4160  }
4161  SAL_INFO( "sw.ww8", "</OutWW8_TableNodeInfoInner>" );
4162 }
4163 
4165 {
4166 
4168  m_pTableInfo->getTableNodeInfo( &rNode );
4169 
4170  if (pNodeInfo.get() != nullptr)
4171  {
4172 #ifdef DBG_UTIL
4173  SAL_INFO( "sw.ww8", pNodeInfo->toString());
4174 #endif
4175  const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
4176  ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aIt(aInners.rbegin());
4177  ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aEnd(aInners.rend());
4178  while (aIt != aEnd)
4179  {
4180  ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
4181 
4182  AttrOutput().TableNodeInfoInner(pInner);
4183  ++aIt;
4184  }
4185  }
4186  SAL_INFO( "sw.ww8", "</OutWW8_SwStartNode>" );
4187 }
4188 
4190 {
4191 #ifdef DBG_UTIL
4192  SAL_INFO( "sw.ww8", "<OutWW8_SwEndNode>" << dbg_out(&rNode));
4193 #endif
4194 
4195  ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = m_pTableInfo->getTableNodeInfo( &rNode );
4196 
4197  if (pNodeInfo.get() != nullptr)
4198  {
4199 #ifdef DBG_UTIL
4200  SAL_INFO( "sw.ww8", pNodeInfo->toString());
4201 #endif
4202  const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
4203  for (const auto& rEntry : aInners)
4204  {
4205  ww8::WW8TableNodeInfoInner::Pointer_t pInner = rEntry.second;
4206  AttrOutput().TableNodeInfoInner(pInner);
4207  }
4208  }
4209  SAL_INFO( "sw.ww8", "</OutWW8_SwEndNode>" );
4210 }
4211 
4213 {
4214  if (m_pKeyMap == nullptr)
4215  {
4216  m_pKeyMap.reset(new NfKeywordTable);
4217  NfKeywordTable & rKeywordTable = *m_pKeyMap;
4218  rKeywordTable[NF_KEY_D] = "d";
4219  rKeywordTable[NF_KEY_DD] = "dd";
4220  rKeywordTable[NF_KEY_DDD] = "ddd";
4221  rKeywordTable[NF_KEY_DDDD] = "dddd";
4222  rKeywordTable[NF_KEY_M] = "M";
4223  rKeywordTable[NF_KEY_MM] = "MM";
4224  rKeywordTable[NF_KEY_MMM] = "MMM";
4225  rKeywordTable[NF_KEY_MMMM] = "MMMM";
4226  rKeywordTable[NF_KEY_NN] = "ddd";
4227  rKeywordTable[NF_KEY_NNN] = "dddd";
4228  rKeywordTable[NF_KEY_NNNN] = "dddd";
4229  rKeywordTable[NF_KEY_YY] = "yy";
4230  rKeywordTable[NF_KEY_YYYY] = "yyyy";
4231  rKeywordTable[NF_KEY_H] = "H";
4232  rKeywordTable[NF_KEY_HH] = "HH";
4233  rKeywordTable[NF_KEY_MI] = "m";
4234  rKeywordTable[NF_KEY_MMI] = "mm";
4235  rKeywordTable[NF_KEY_S] = "s";
4236  rKeywordTable[NF_KEY_SS] = "ss";
4237  rKeywordTable[NF_KEY_AMPM] = "AM/PM";
4238  }
4239 
4240  return *m_pKeyMap;
4241 }
4242 
4243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
NF_KEY_NN
void WriteMainText()
Definition: wrtww8.cxx:2856
std::shared_ptr< NfKeywordTable > m_pKeyMap
Definition: wrtww8.hxx:467
#define sMainStream
Definition: wrtww8.cxx:453
long GetLeft() const
bool WriteGenericText(WW8Export &rWrt, sal_uInt8 nTTyp, WW8_CP &rCount)
Definition: wrtw8sty.cxx:2018
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:481
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:963
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:8503
IDocumentStatistics const & getIDocumentStatistics() const
Definition: doc.cxx:405
NF_KEY_MI
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
virtual void TableInfoRow(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo) override
Definition: wrtww8.cxx:2029
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:3740
sal_uLong Count() const
Definition: ndarr.hxx:143
const sal_uInt16 sprmPFInnerTtp
Definition: sprmids.hxx:414
#define WW_BLOCKSIZE
Definition: ww8par.cxx:5497
std::unique_ptr< ww::bytes > pO
Buffer.
Definition: wrtww8.hxx:966
virtual sal_uInt32 Getn32DummyCompatibilityOptions2() const =0
Get the n32DummyCompatabilityOptions2.
std::unique_ptr< SvxMSExportOLEObjects > m_pOLEExp
Definition: wrtww8.hxx:468
virtual bool InitCipher(sal_uInt32 nCounter) override
const SwFormatCol & GetCol(bool=true) const
Definition: fmtclds.hxx:168
SvStream * pTableStrm
Definition: wrtww8.hxx:968
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:3701
Marks a position in the document model.
Definition: pam.hxx:35
void OutSwString(const OUString &, sal_Int32 nStt, sal_Int32 nLen)
Definition: wrtww8.cxx:1861
void AddRangeStartPosition(const OUString &rName, WW8_CP nStartCp, bool bIgnoreEmpty)
Definition: wrtw8sty.cxx:1975
void MoveFieldMarks(WW8_CP nFrom, WW8_CP nTo)
Definition: wrtww8.cxx:1510
std::unique_ptr< WW8_WrPlcField > m_pFieldHFTextBxs
Definition: wrtww8.hxx:523
bool IsSectionNode() const
Definition: node.hxx:644
std::unique_ptr< WW8Fib > pFib
File Information Block.
Definition: wrtww8.hxx:970
virtual AttributeOutputBase & AttrOutput() const override
memory leak #i120098#, to hold the reference to unnamed SotStorage obj
Definition: wrtww8.cxx:3681
bool m_bEndAtTextEnd
Definition: wrtww8.hxx:555
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:2595
std::unique_ptr< WW8_WrPlcField > m_pFieldHdFt
Definition: wrtww8.hxx:518
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:439
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:515
bool m_bAddFootnoteTab
Definition: wrtww8.hxx:565
virtual const SwRootFrame * GetCurrentLayout() const =0
NF_KEY_NNNN
SvStream & WriteInt32(sal_Int32 nInt32)
bool m_bFootnoteAtTextEnd
Definition: wrtww8.hxx:554
SwDocShell * GetDocShell()
Definition: doc.hxx:1340
SwPaM * m_pCurrentPam
Definition: shellio.hxx:404
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:983
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
bool WriteText(WW8Export &rWrt)
Definition: wrtww8.cxx:3721
virtual void OutputEndNode(const SwEndNode &)
Output SwEndNode.
Definition: wrtww8.cxx:4189
#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:458
virtual void TableDefinition(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo) override
Definition: wrtww8.cxx:2326
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:2906
SAL_DLLPUBLIC_EXPORT sal_uInt32 SaveOrDelMSVBAStorage_ww8(SfxObjectShell &rDoc, SotStorage &rStor, sal_Bool bSaveInto, const OUString &rStorageName)
Definition: wrtww8.cxx:3705
BitmapChecksum GetChecksum() const
short nStartGrp
Definition: wrtww8.cxx:136
long GetWidth() const
sal_uLong m_nCurStart
Definition: wrtww8.hxx:568
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:517
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:1920
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:902
const SwPosition * GetMark() const
Definition: pam.hxx:209
const SwAttrSet * m_pStyAttr
Definition: wrtww8.hxx:529
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:460
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:442
bool m_bOutPageDescs
PageDescs (section properties) are being written.
Definition: wrtww8.hxx:546
Definition: doc.hxx:185
ePLCFT ePlc
Definition: wrtww8.hxx:1292
#define ODF_FORMCHECKBOX
virtual void TableBidi(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo) override
Definition: wrtww8.cxx:2181
sal_Int32 dttmCreated
Definition: ww8scan.hxx:1669
sal_Int32 cLines
Definition: ww8scan.hxx:1687
sal_uLong nDataLen
Definition: wrtww8.hxx:1311
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:2197
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:473
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
virtual void WriteNumbering() override
Output the numbering table.
Definition: wrtw8num.cxx:134
SwNode & GetNode() const
Definition: ndindex.hxx:118
long SwTwips
Definition: swtypes.hxx:49
Point * m_pFlyOffset
Definition: wrtww8.hxx:514
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:475
void ExportDopTypography(WW8DopTypography &rTypo)
Definition: wrtww8.cxx:602
sal_uInt8 const nTyp
Definition: wrtww8.hxx:1212
bool IsImpress2PowerPoint() const
void SetParaBreak()
Definition: wrtww8.cxx:1424
bool bOldOutTable
Definition: wrtww8.hxx:443
WW8_CP Fc2Cp(sal_uLong nFc) const
Definition: wrtww8.hxx:1080
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:522
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:547
virtual void AppendSmartTags(SwTextNode &rTextNode) override
Definition: wrtww8.cxx:1500
sal_uInt16 Count() const
Definition: wrtww8.hxx:1317
void Write(WW8Export &rExport)
Definition: wrtww8.cxx:3818
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:469
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:520
WW8_CP Fc2Cp(sal_uLong nFc) const
Definition: wrtww8.cxx:1430
sal_uLong m_nStart
Definition: wrtww8.cxx:2674
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:521
OUString m_aTag
Definition: ww8struc.hxx:1101
virtual void TableCanSplit(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo) override
Definition: wrtww8.cxx:2161
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:495
sal_uInt16 nFkpStartPage
Definition: wrtww8.hxx:1291
OUString BookmarkToWord(const OUString &rBookmark)
Definition: wrtw8nds.cxx:1173
WW8Export * m_pExport
Definition: wrtww8.hxx:913
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:405
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:2125
void AddLinkTarget(const OUString &rURL)
Definition: wrtww8.cxx:3054
sal_Int32 cCh
Definition: ww8scan.hxx:1675
void WriteText()
Iterate through the nodes and call the appropriate OutputNode() on them.
Definition: wrtww8.cxx:2712
std::vector< MSOProperty > m_aProperties
Definition: ww8struc.hxx:1139
SwEscherEx * m_pEscher
Definition: wrtww8.hxx:536
WW8Export & rWrt
Definition: wrtww8.hxx:1288
sal_uInt16 sal_Unicode
bool bOldStartTOX
Definition: wrtww8.hxx:445
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:2452
std::unique_ptr< WW8_WrPlcField > m_pFieldFootnote
Definition: wrtww8.hxx:519
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:3575
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:2683
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:507
Class to collect and output the styles table.
Definition: wrtww8.hxx:1543
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
#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:2463
SAL_DLLPUBLIC_EXPORT void ExportDOC(const OUString &rFltName, const OUString &rBaseURL, WriterRef &xRet)
Definition: wrtww8.cxx:3711
void WritePlc(WW8Export &rWrt) const
Definition: wrtww8.cxx:3772
sal_Unicode m_rgxchFPunct[nMaxFollowing]
Definition: ww8struc.hxx:415
std::vector< WW8_CP > aPos
Definition: wrtww8.hxx:1309
const sal_uInt16 sprmTFBiDi
Definition: sprmids.hxx:459
sal_uInt8 nTyp
Definition: wrtww8.hxx:1263
bool IsStartNode() const
Definition: node.hxx:624
bool m_bInWriteEscher
Definition: wrtww8.hxx:551
sal_uInt32 m_cvBack
Definition: wrtww8.hxx:1611
virtual void TableDefaultBorders(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo) override
Definition: wrtww8.cxx:2539
bool IsCalc2Excel() const
void SetCompatibilityOptions(sal_uInt32 a32Bit)
Definition: ww8scan.cxx:7895
bool bOldFlyFrameAttrs
Definition: wrtww8.hxx:444
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:446
const sal_uInt16 sprmTTableWidth
Definition: sprmids.hxx:468
void Finish(sal_uLong nLastCp, sal_uLong nStartCp)
Definition: wrtww8.cxx:850
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:2193
MainTextPlcDrawObj * m_pSdrObjs
Definition: wrtww8.hxx:533
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:1898
WW8_WrPlcTextBoxes * m_pTextBxs
Definition: wrtww8.hxx:497
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:471
virtual css::uno::Sequence< css::beans::NamedValue > GetEncryptionData()
MSWordExportBase(SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam)
Definition: wrtww8.cxx:3589
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:1403
void Append(WW8_CP nCp, sal_uLong nData)
Definition: wrtww8.cxx:939
sal_uInt16 const nStructSiz
Definition: wrtww8.hxx:1312
#define ERRCODE_IO_NOTSUPPORTED
void SetBaseURL(const OUString &rURL)
Definition: shellio.hxx:393
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:474
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:403
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:491
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:3075
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
sal_uLong m_nCurEnd
Definition: wrtww8.hxx:568
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