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