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