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