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