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