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