LibreOffice Module sw (master)  1
wrtw8nds.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 <vector>
21 #include <list>
22 #include <utility>
23 #include <algorithm>
24 #include <iostream>
25 
26 #include <oox/core/filterbase.hxx>
27 #include "docxexport.hxx"
28 #include "docxexportfilter.hxx"
29 
30 #include <i18nlangtag/mslangid.hxx>
31 #include <hintids.hxx>
32 #include <tools/urlobj.hxx>
33 #include <editeng/boxitem.hxx>
34 #include <editeng/cmapitem.hxx>
35 #include <editeng/langitem.hxx>
36 #include <editeng/svxfont.hxx>
37 #include <editeng/lrspitem.hxx>
38 #include <editeng/brushitem.hxx>
39 #include <editeng/fontitem.hxx>
40 #include <editeng/keepitem.hxx>
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/ulspitem.hxx>
44 #include <editeng/frmdiritem.hxx>
45 #include <editeng/tstpitem.hxx>
46 #include <svl/grabbagitem.hxx>
47 #include <svl/urihelper.hxx>
48 #include <svl/whiter.hxx>
49 #include <fmtpdsc.hxx>
50 #include <fmtfsize.hxx>
51 #include <fmtornt.hxx>
52 #include <fmtlsplt.hxx>
53 #include <fmtflcnt.hxx>
54 #include <fmtanchr.hxx>
55 #include <fmtcntnt.hxx>
56 #include <frmatr.hxx>
57 #include <paratr.hxx>
58 #include <txatbase.hxx>
59 #include <fmtinfmt.hxx>
60 #include <fmtrfmrk.hxx>
61 #include <fchrfmt.hxx>
62 #include <fmtautofmt.hxx>
63 #include <charfmt.hxx>
64 #include <tox.hxx>
65 #include <ndtxt.hxx>
66 #include <pam.hxx>
67 #include <doc.hxx>
69 #include <IDocumentMarkAccess.hxx>
70 #include <docary.hxx>
71 #include <swtable.hxx>
72 #include <swtblfmt.hxx>
73 #include <section.hxx>
74 #include <pagedesc.hxx>
75 #include <swrect.hxx>
76 #include <reffld.hxx>
77 #include <redline.hxx>
78 #include <wrtswtbl.hxx>
79 #include <htmltbl.hxx>
80 #include <txttxmrk.hxx>
81 #include <fmtline.hxx>
82 #include <fmtruby.hxx>
83 #include <breakit.hxx>
84 #include <txtatr.hxx>
85 #include <fmtsrnd.hxx>
86 #include <fmtrowsplt.hxx>
87 #include <com/sun/star/drawing/XShape.hpp>
88 #include <com/sun/star/i18n/BreakIterator.hpp>
89 #include <com/sun/star/i18n/ScriptType.hpp>
90 #include <com/sun/star/i18n/WordType.hpp>
91 #include <com/sun/star/text/RubyPosition.hpp>
92 #include <oox/export/vmlexport.hxx>
93 #include <sfx2/docfile.hxx>
94 #include <sal/log.hxx>
96 
97 #include "sprmids.hxx"
98 
99 #include "writerhelper.hxx"
100 #include "writerwordglue.hxx"
101 #include <numrule.hxx>
102 #include "wrtww8.hxx"
103 #include "ww8par.hxx"
104 #include <IMark.hxx>
105 #include "ww8attributeoutput.hxx"
106 
107 #include <ndgrf.hxx>
108 #include <ndole.hxx>
109 
110 #include <cstdio>
111 
112 using namespace ::com::sun::star;
113 using namespace ::com::sun::star::i18n;
114 using namespace sw::util;
115 using namespace sw::types;
116 using namespace sw::mark;
117 using namespace ::oox::vml;
118 
119 static OUString lcl_getFieldCode( const IFieldmark* pFieldmark )
120 {
121  OSL_ENSURE(pFieldmark!=nullptr, "where is my fieldmark???");
122 
123  if ( !pFieldmark)
124  return OUString();
125  if ( pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
126  return " FORMTEXT ";
127  if ( pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN )
128  return " FORMDROPDOWN ";
129  if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
130  return " FORMCHECKBOX ";
131  if ( pFieldmark->GetFieldname( ) == ODF_FORMDATE )
132  return " ODFFORMDATE ";
133  if ( pFieldmark->GetFieldname( ) == ODF_TOC )
134  return " TOC ";
135  if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
136  return " HYPERLINK ";
137  if ( pFieldmark->GetFieldname( ) == ODF_PAGEREF )
138  return " PAGEREF ";
139  return pFieldmark->GetFieldname();
140 }
141 
142 static ww::eField lcl_getFieldId( const IFieldmark* pFieldmark ) {
143  OSL_ENSURE(pFieldmark!=nullptr, "where is my fieldmark???");
144  if ( !pFieldmark )
145  return ww::eUNKNOWN;
146  if ( pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
147  return ww::eFORMTEXT;
148  if ( pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN )
149  return ww::eFORMDROPDOWN;
150  if ( pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX )
151  return ww::eFORMCHECKBOX;
152  if ( pFieldmark->GetFieldname( ) == ODF_FORMDATE )
153  return ww::eFORMDATE;
154  if ( pFieldmark->GetFieldname( ) == ODF_TOC )
155  return ww::eTOC;
156  if ( pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
157  return ww::eHYPERLINK;
158  if ( pFieldmark->GetFieldname( ) == ODF_PAGEREF )
159  return ww::ePAGEREF;
160  return ww::eUNKNOWN;
161 }
162 
164  : pOld( rExport.m_pChpIter ), m_rExport( rExport )
165 {
166  m_rExport.m_pChpIter = this;
167 }
168 
170 {
172 }
173 
175 {
176 public:
177  bool operator()(const ww8::Frame &rOne, const ww8::Frame &rTwo) const
178  {
179  return rOne.GetPosition() < rTwo.GetPosition();
180  }
181 };
182 
184 {
185  OSL_ENSURE(maCharRuns.begin() != maCharRuns.end(), "Impossible");
186  mnScript = maCharRunIter->mnScript;
187  meChrSet = maCharRunIter->meCharSet;
188  mbCharIsRTL = maCharRunIter->mbRTL;
189 }
190 
192  MSWordAttrIter(rWr),
193  rNd(rTextNd),
194  maCharRuns(GetPseudoCharRuns(rTextNd)),
195  pCurRedline(nullptr),
196  nCurrentSwPos(0),
197  nCurRedlinePos(SwRedlineTable::npos),
198  mrSwFormatDrop(rTextNd.GetSwAttrSet().GetDrop())
199 {
200 
201  SwPosition aPos(rTextNd);
202  mbParaIsRTL = SvxFrameDirection::Horizontal_RL_TB == rWr.m_pDoc->GetTextDirection(aPos);
203 
204  maCharRunIter = maCharRuns.begin();
205  IterToCurrent();
206 
207  /*
208  #i2916#
209  Get list of any graphics which may be anchored from this paragraph.
210  */
212  std::sort(maFlyFrames.begin(), maFlyFrames.end(), sortswflys());
213 
214  /*
215  #i18480#
216  If we are inside a frame then anything anchored inside this frame can
217  only be supported by word anchored inline ("as character"), so force
218  this in the supportable case.
219  */
220  if (rWr.m_bInWriteEscher)
221  {
222  for ( auto& aFlyFrame : maFlyFrames )
223  aFlyFrame.ForceTreatAsInline();
224  }
225 
226  maFlyIter = maFlyFrames.begin();
227 
229  {
230  SwPosition aPosition( rNd, SwIndex( const_cast<SwTextNode*>(&rNd) ) );
232  }
233 
235 }
236 
237 static sal_Int32 lcl_getMinPos( sal_Int32 pos1, sal_Int32 pos2 )
238 {
239  if ( pos1 >= 0 && pos2 >= 0 )
240  {
241  // both valid: return minimum one
242  return std::min(pos1, pos2);
243  }
244 
245  // return the valid one, if any, or -1
246  return std::max(pos1, pos2);
247 }
248 
249 sal_Int32 SwWW8AttrIter::SearchNext( sal_Int32 nStartPos )
250 {
251  const OUString aText = rNd.GetText();
252  sal_Int32 fieldEndPos = aText.indexOf(CH_TXT_ATR_FIELDEND, nStartPos);
253  sal_Int32 fieldStartPos = aText.indexOf(CH_TXT_ATR_FIELDSTART, nStartPos);
254  sal_Int32 formElementPos = aText.indexOf(CH_TXT_ATR_FORMELEMENT, nStartPos);
255 
256  const sal_Int32 pos = lcl_getMinPos(
257  lcl_getMinPos( fieldEndPos, fieldStartPos ),
258  formElementPos );
259 
260  sal_Int32 nMinPos = (pos>=0) ? pos : SAL_MAX_INT32;
261 
262  // first the redline, then the attributes
263  if( pCurRedline )
264  {
265  const SwPosition* pEnd = pCurRedline->End();
266  if (pEnd->nNode == rNd)
267  {
268  const sal_Int32 i = pEnd->nContent.GetIndex();
269  if ( i >= nStartPos && i < nMinPos )
270  {
271  nMinPos = i;
272  }
273  }
274  }
275 
276  if ( nCurRedlinePos < m_rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable().size() )
277  {
278  // nCurRedlinePos point to the next redline
280  if( pCurRedline )
281  ++nRedLinePos;
282 
283  for ( ; nRedLinePos < m_rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable().size(); ++nRedLinePos )
284  {
285  const SwRangeRedline* pRedl = m_rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable()[ nRedLinePos ];
286 
287  const SwPosition* pStt = pRedl->Start();
288  const SwPosition* pEnd = pStt == pRedl->GetPoint()
289  ? pRedl->GetMark()
290  : pRedl->GetPoint();
291 
292  if( pStt->nNode == rNd )
293  {
294  const sal_Int32 i = pStt->nContent.GetIndex();
295  if( i >= nStartPos && i < nMinPos )
296  nMinPos = i;
297  }
298  else
299  break;
300 
301  if( pEnd->nNode == rNd )
302  {
303  const sal_Int32 i = pEnd->nContent.GetIndex();
304  if( i >= nStartPos && i < nMinPos )
305  {
306  nMinPos = i;
307  }
308  }
309  }
310  }
311 
312  if (mrSwFormatDrop.GetWholeWord() && nStartPos <= rNd.GetDropLen(0))
313  nMinPos = rNd.GetDropLen(0);
314  else if(nStartPos <= mrSwFormatDrop.GetChars())
315  nMinPos = mrSwFormatDrop.GetChars();
316 
317  if(const SwpHints* pTextAttrs = rNd.GetpSwpHints())
318  {
319 
320 // can be optimized if we consider that the TextAttrs are sorted by start position.
321 // but then we'd have to save 2 indices
322  for( size_t i = 0; i < pTextAttrs->Count(); ++i )
323  {
324  const SwTextAttr* pHt = pTextAttrs->Get(i);
325  sal_Int32 nPos = pHt->GetStart(); // first Attr characters
326  if( nPos >= nStartPos && nPos <= nMinPos )
327  nMinPos = nPos;
328 
329  if( pHt->End() ) // Attr with end
330  {
331  nPos = *pHt->End(); // last Attr character + 1
332  if( nPos >= nStartPos && nPos <= nMinPos )
333  nMinPos = nPos;
334  }
335  if (pHt->HasDummyChar())
336  {
337  // pos + 1 because of CH_TXTATR in Text
338  nPos = pHt->GetStart() + 1;
339  if( nPos >= nStartPos && nPos <= nMinPos )
340  nMinPos = nPos;
341  }
342  }
343  }
344 
345  if (maCharRunIter != maCharRuns.end())
346  {
347  if (maCharRunIter->mnEndPos < nMinPos)
348  nMinPos = maCharRunIter->mnEndPos;
349  IterToCurrent();
350  }
351 
352  /*
353  #i2916#
354  Check to see if there are any graphics anchored to characters in this
355  paragraph's text. Set nMinPos to 1 past the placement for anchored to
356  character because anchors in Word appear after the character they are
357  anchored to.
358  */
359  if (maFlyIter != maFlyFrames.end())
360  {
361  const SwPosition &rAnchor = maFlyIter->GetPosition();
362 
363  sal_Int32 nPos = rAnchor.nContent.GetIndex();
364  if (nPos >= nStartPos && nPos <= nMinPos)
365  nMinPos = nPos;
366 
367  if (maFlyIter->GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR)
368  {
369  ++nPos;
370  if (nPos >= nStartPos && nPos <= nMinPos)
371  nMinPos = nPos;
372  }
373  }
374 
375  //nMinPos found and not going to change at this point
376 
377  if (maCharRunIter != maCharRuns.end())
378  {
379  if (maCharRunIter->mnEndPos == nMinPos)
380  ++maCharRunIter;
381  }
382 
383  return nMinPos;
384 }
385 
386 void SwWW8AttrIter::OutAttr( sal_Int32 nSwPos, bool bWriteCombChars)
387 {
389 
390  /*
391  Depending on whether text is in CTL/CJK or Western, get the id of that
392  script, the idea is that the font that is actually in use to render this
393  range of text ends up in pFont
394  */
395  sal_uInt16 nFontId = GetWhichOfScript( RES_CHRATR_FONT, GetScript() );
396 
397  const SvxFontItem &rParentFont = ItemGet<SvxFontItem>(
398  static_cast<const SwTextFormatColl&>(rNd.GetAnyFormatColl()), nFontId);
399  const SvxFontItem *pFont = &rParentFont;
400  const SfxPoolItem *pGrabBag = nullptr;
401 
402  SfxItemSet aExportSet(*rNd.GetSwAttrSet().GetPool(),
404 
405  //The hard formatting properties that affect the entire paragraph
406  if (rNd.HasSwAttrSet())
407  {
408  // only copy hard attributes - bDeep = false
409  aExportSet.Set(rNd.GetSwAttrSet(), false/*bDeep*/);
410  // get the current font item. Use rNd.GetSwAttrSet instead of aExportSet:
411  const SvxFontItem &rNdFont = ItemGet<SvxFontItem>(rNd.GetSwAttrSet(), nFontId);
412  pFont = &rNdFont;
413  aExportSet.ClearItem(nFontId);
414  }
415 
416  //The additional hard formatting properties that affect this range in the
417  //paragraph
418  ww8::PoolItems aRangeItems;
419  if (const SwpHints* pTextAttrs = rNd.GetpSwpHints())
420  {
421  for( size_t i = 0; i < pTextAttrs->Count(); ++i )
422  {
423  const SwTextAttr* pHt = pTextAttrs->Get(i);
424  const sal_Int32* pEnd = pHt->End();
425 
426  if (pEnd ? ( nSwPos >= pHt->GetStart() && nSwPos < *pEnd)
427  : nSwPos == pHt->GetStart() )
428  {
429  sal_uInt16 nWhich = pHt->GetAttr().Which();
430  if (nWhich == RES_TXTATR_AUTOFMT)
431  {
432  const SwFormatAutoFormat& rAutoFormat = static_cast<const SwFormatAutoFormat&>(pHt->GetAttr());
433  const std::shared_ptr<SfxItemSet>& pSet = rAutoFormat.GetStyleHandle();
434  SfxWhichIter aIter( *pSet );
435  const SfxPoolItem* pItem;
436  sal_uInt16 nWhichId = aIter.FirstWhich();
437  while( nWhichId )
438  {
439  if( SfxItemState::SET == pSet->GetItemState( nWhichId, false, &pItem ))
440  {
441  if (nWhichId == nFontId)
442  pFont = &(item_cast<SvxFontItem>(*pItem));
443  else if (nWhichId == RES_CHRATR_GRABBAG)
444  pGrabBag = pItem;
445  else
446  aRangeItems[nWhichId] = pItem;
447  }
448  nWhichId = aIter.NextWhich();
449  }
450  }
451  else
452  aRangeItems[nWhich] = (&(pHt->GetAttr()));
453  }
454  else if (nSwPos < pHt->GetStart())
455  break;
456  }
457  }
458 
459  /*
460  For #i24291# we need to explicitly remove any properties from the
461  aExportSet which a SwCharFormat would override, we can't rely on word doing
462  this for us like writer does
463  */
464  const SwFormatCharFormat *pCharFormatItem =
465  HasItem< SwFormatCharFormat >( aRangeItems, RES_TXTATR_CHARFMT );
466  if ( pCharFormatItem )
467  ClearOverridesFromSet( *pCharFormatItem, aExportSet );
468 
469  // tdf#113790: AutoFormat style overwrites char style, so remove all
470  // elements from CHARFMT grab bag which are set in AUTOFMT grab bag
471  if (const SfxGrabBagItem *pAutoFmtGrabBag = dynamic_cast<const SfxGrabBagItem*>(pGrabBag))
472  {
473  if (const SfxGrabBagItem *pCharFmtGrabBag = aExportSet.GetItem<SfxGrabBagItem>(RES_CHRATR_GRABBAG, false))
474  {
475  std::unique_ptr<SfxGrabBagItem> pNewCharFmtGrabBag(static_cast<SfxGrabBagItem*>(pCharFmtGrabBag->Clone()));
476  assert(pNewCharFmtGrabBag);
477  auto & rNewFmtMap = pNewCharFmtGrabBag->GetGrabBag();
478  for (auto const & item : pAutoFmtGrabBag->GetGrabBag())
479  {
480  if (item.second.hasValue())
481  rNewFmtMap.erase(item.first);
482  }
483  aExportSet.Put(std::move(pNewCharFmtGrabBag));
484  }
485  }
486 
487  ww8::PoolItems aExportItems;
488  GetPoolItems( aExportSet, aExportItems, false );
489 
490  if( rNd.GetpSwpHints() == nullptr )
491  m_rExport.SetCurItemSet(&aExportSet);
492 
493  for ( const auto& aRangeItem : aRangeItems )
494  {
495  aExportItems[aRangeItem.first] = aRangeItem.second;
496  }
497 
498  if ( !aExportItems.empty() )
499  {
500  const SwModify* pOldMod = m_rExport.m_pOutFormatNode;
502  m_rExport.m_aCurrentCharPropStarts.push( nSwPos );
503 
504  // tdf#38778 Fix output of the font in DOC run for fields
505  const SvxFontItem * pFontToOutput = ( rParentFont != *pFont )? pFont : nullptr;
506 
507  m_rExport.ExportPoolItemsToCHP( aExportItems, GetScript(), pFontToOutput, bWriteCombChars );
508 
509  // HasTextItem only allowed in the above range
511  m_rExport.m_pOutFormatNode = pOldMod;
512  }
513 
514  if( rNd.GetpSwpHints() == nullptr )
515  m_rExport.SetCurItemSet(nullptr);
516 
517  OSL_ENSURE( pFont, "must be *some* font associated with this txtnode" );
518  if ( pFont )
519  {
520  SvxFontItem aFont( *pFont );
521 
522  if ( rParentFont != aFont )
523  m_rExport.AttrOutput().OutputItem( aFont );
524  }
525 
526  // Output grab bag attributes
527  if (pGrabBag)
528  m_rExport.AttrOutput().OutputItem( *pGrabBag );
529 }
530 
532 {
533  if (maFlyFrames.size() != 1)
534  return false;
535 
536  while ( maFlyIter != maFlyFrames.end() )
537  {
538  const SdrObject* pSdrObj = maFlyIter->GetFrameFormat().FindRealSdrObject();
539 
540  if (pSdrObj)
541  {
542  if (VMLExport::IsWaterMarkShape(pSdrObj->GetName()))
543  return true;
544  }
545  ++maFlyIter;
546  }
547 
548  return false;
549 }
550 
552 {
553  ww8::FrameIter aTmpFlyIter = maFlyIter ;
554 
555  while ( aTmpFlyIter != maFlyFrames.end() )
556  {
557  const SwPosition &rAnchor = maFlyIter->GetPosition();
558  sal_uLong nAnchorPos = rAnchor.nNode.GetIndex();
559  /* if current node position and the anchor position are the same
560  then the frame anchor is linked to this node
561  */
562  if ( nAnchorPos == nNodePos )
563  return true ;
564 
565  ++aTmpFlyIter;
566  }
567  return false ;
568 }
569 
570 bool SwWW8AttrIter::HasFlysAt(sal_Int32 nSwPos) const
571 {
572  for (const auto& rFly : maFlyFrames)
573  {
574  const SwPosition& rAnchor = rFly.GetPosition();
575  const sal_Int32 nPos = rAnchor.nContent.GetIndex();
576  if (nPos == nSwPos)
577  {
578  return true;
579  }
580  }
581 
582  return false;
583 }
584 
586 {
587  // collection point to first gather info about all of the potentially linked textboxes: to be analyzed later.
588  OUString sLinkChainName;
589  ww8::FrameIter linkedTextboxesIter = maFlyIter;
590  while ( linkedTextboxesIter != maFlyFrames.end() )
591  {
592  uno::Reference< drawing::XShape > xShape;
593  ww8::Frame aFrame = *linkedTextboxesIter;
594  const SdrObject* pSdrObj = aFrame.GetFrameFormat().FindRealSdrObject();
595  if( pSdrObj )
596  xShape.set(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY);
597  uno::Reference< beans::XPropertySet > xPropertySet(xShape, uno::UNO_QUERY);
598  uno::Reference< beans::XPropertySetInfo > xPropertySetInfo;
599  if( xPropertySet.is() )
600  xPropertySetInfo = xPropertySet->getPropertySetInfo();
601  if( xPropertySetInfo.is() )
602  {
603  MSWordExportBase::LinkedTextboxInfo aLinkedTextboxInfo;
604 
605  if( xPropertySetInfo->hasPropertyByName("LinkDisplayName") )
606  xPropertySet->getPropertyValue("LinkDisplayName") >>= sLinkChainName;
607  else if( xPropertySetInfo->hasPropertyByName("ChainName") )
608  xPropertySet->getPropertyValue("ChainName") >>= sLinkChainName;
609 
610  if( xPropertySetInfo->hasPropertyByName("ChainNextName") )
611  xPropertySet->getPropertyValue("ChainNextName") >>= aLinkedTextboxInfo.sNextChain;
612  if( xPropertySetInfo->hasPropertyByName("ChainPrevName") )
613  xPropertySet->getPropertyValue("ChainPrevName") >>= aLinkedTextboxInfo.sPrevChain;
614 
615  //collect a list of linked textboxes: those with a NEXT or PREVIOUS link
616  if( !aLinkedTextboxInfo.sNextChain.isEmpty() || !aLinkedTextboxInfo.sPrevChain.isEmpty() )
617  {
618  assert( !sLinkChainName.isEmpty() );
619 
620  //there are many discarded duplicates in documents - no duplicates allowed in the list, so try to find the real one.
621  //if this LinkDisplayName/ChainName already exists on a different shape...
622  // the earlier processed duplicates are thrown out unless this one can be proved as bad. (last processed duplicate usually is stored)
623  auto linkFinder = m_rExport.m_aLinkedTextboxesHelper.find(sLinkChainName);
624  if( linkFinder != m_rExport.m_aLinkedTextboxesHelper.end() )
625  {
626  //If my NEXT/PREV targets have already been discovered, but don't match me, then assume I'm an abandoned remnant
627  // (this logic fails if both me and one of my links are duplicated, and the remnants were added first.)
628  linkFinder = m_rExport.m_aLinkedTextboxesHelper.find(aLinkedTextboxInfo.sNextChain);
629  if( (linkFinder != m_rExport.m_aLinkedTextboxesHelper.end()) && (linkFinder->second.sPrevChain != sLinkChainName) )
630  {
631  ++linkedTextboxesIter;
632  break;
633  }
634 
635  linkFinder = m_rExport.m_aLinkedTextboxesHelper.find(aLinkedTextboxInfo.sPrevChain);
636  if( (linkFinder != m_rExport.m_aLinkedTextboxesHelper.end()) && (linkFinder->second.sNextChain != sLinkChainName) )
637  {
638  ++linkedTextboxesIter;
639  break;
640  }
641  }
643  m_rExport.m_aLinkedTextboxesHelper[sLinkChainName] = aLinkedTextboxInfo;
644  }
645  }
646  ++linkedTextboxesIter;
647  }
648 
649  /*
650  #i2916#
651  May have an anchored graphic to be placed, loop through sorted array
652  and output all at this position
653  */
654  while ( maFlyIter != maFlyFrames.end() )
655  {
656  const SwPosition &rAnchor = maFlyIter->GetPosition();
657  const sal_Int32 nPos = rAnchor.nContent.GetIndex();
658 
659  if ( nPos != nSwPos )
660  return FLY_NOT_PROCESSED ; // We haven't processed the fly
661 
662  const SdrObject* pSdrObj = maFlyIter->GetFrameFormat().FindRealSdrObject();
663 
664  if (pSdrObj)
665  {
666  if (VMLExport::IsWaterMarkShape(pSdrObj->GetName()))
667  {
668  // This is a watermark object. Should be written ONLY in the header
670  {
671  // Should write a watermark in the header
673  }
674  else
675  {
676  // Should not write watermark object in the main body text
677  }
678  }
679  else
680  {
681  // This is not a watermark object - write normally
683  }
684  }
685  else
686  {
687  // This is not a watermark object - write normally
689  }
690  ++maFlyIter;
691  }
693 }
694 
695 bool SwWW8AttrIter::IsTextAttr( sal_Int32 nSwPos ) const
696 {
697  // search for attrs with dummy character or content
698  if (const SwpHints* pTextAttrs = rNd.GetpSwpHints())
699  {
700  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
701  {
702  const SwTextAttr* pHt = pTextAttrs->Get(i);
703  if (nSwPos == pHt->GetStart())
704  {
705  if (pHt->HasDummyChar() || pHt->HasContent() )
706  {
707  return true;
708  }
709  }
710  else if (nSwPos < pHt->GetStart())
711  {
712  break; // sorted by start
713  }
714  }
715  }
716 
717  return false;
718 }
719 
720 bool SwWW8AttrIter::IsExportableAttr(sal_Int32 nSwPos) const
721 {
722  if (const SwpHints* pTextAttrs = rNd.GetpSwpHints())
723  {
724  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
725  {
726  const SwTextAttr* pHt = pTextAttrs->GetSortedByEnd(i);
727  const sal_Int32 nStart = pHt->GetStart();
728  const sal_Int32 nEnd = pHt->End() ? *pHt->End() : INT_MAX;
729  if (nSwPos >= nStart && nSwPos < nEnd)
730  {
731  switch (pHt->GetAttr().Which())
732  {
733  // Metadata fields should be dynamically generated, not dumped as text.
735  return false;
736  }
737  }
738  }
739  }
740 
741  return true;
742 }
743 
744 bool SwWW8AttrIter::IsDropCap( int nSwPos )
745 {
746  // see if the current position falls on a DropCap
747  int nDropChars = mrSwFormatDrop.GetChars();
748  bool bWholeWord = mrSwFormatDrop.GetWholeWord();
749  if (bWholeWord)
750  {
751  const sal_Int32 nWordLen = rNd.GetDropLen(0);
752  if(nSwPos == nWordLen && nSwPos != 0)
753  return true;
754  }
755  else
756  {
757  if (nSwPos == nDropChars && nSwPos != 0)
758  return true;
759  }
760  return false;
761 }
762 
764 {
765  return std::any_of(m_rExport.m_aImplicitBookmarks.begin(), m_rExport.m_aImplicitBookmarks.end(),
766  [this](const aBookmarkPair& rBookmarkPair) { return rBookmarkPair.second == rNd.GetIndex(); });
767 }
768 
769 //HasItem is for the summary of the double attributes: Underline and WordlineMode as TextItems.
770 // OutAttr () calls the output function, which can call HasItem() for other items at the attribute's start position.
771 // Only attributes with end can be queried.
772 // It searches with bDeep
773 const SfxPoolItem* SwWW8AttrIter::HasTextItem( sal_uInt16 nWhich ) const
774 {
775  const SfxPoolItem* pRet = nullptr;
776  const SwpHints* pTextAttrs = rNd.GetpSwpHints();
777  if (pTextAttrs && !m_rExport.m_aCurrentCharPropStarts.empty())
778  {
779  const sal_Int32 nTmpSwPos = m_rExport.m_aCurrentCharPropStarts.top();
780  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
781  {
782  const SwTextAttr* pHt = pTextAttrs->Get(i);
783  const SfxPoolItem* pItem = &pHt->GetAttr();
784  const sal_Int32 * pAtrEnd = nullptr;
785  if( nullptr != ( pAtrEnd = pHt->End() ) && // only Attr with an end
786  nTmpSwPos >= pHt->GetStart() && nTmpSwPos < *pAtrEnd )
787  {
788  if ( nWhich == pItem->Which() )
789  {
790  pRet = pItem; // found it
791  break;
792  }
793  else if( RES_TXTATR_INETFMT == pHt->Which() ||
794  RES_TXTATR_CHARFMT == pHt->Which() ||
795  RES_TXTATR_AUTOFMT == pHt->Which() )
796  {
797  const SfxItemSet* pSet = CharFormat::GetItemSet( pHt->GetAttr() );
798  const SfxPoolItem* pCharItem;
799  if ( pSet &&
800  SfxItemState::SET == pSet->GetItemState( nWhich, pHt->Which() != RES_TXTATR_AUTOFMT, &pCharItem ) )
801  {
802  pRet = pCharItem; // found it
803  break;
804  }
805  }
806  }
807  else if (nTmpSwPos < pHt->GetStart())
808  break; // nothing more to come
809  }
810  }
811  return pRet;
812 }
813 
815 {
816  rItems.insert(rItems.end(), pO->begin(), pO->end());
817 }
818 
819 const SfxPoolItem& SwWW8AttrIter::GetItem(sal_uInt16 nWhich) const
820 {
821  const SfxPoolItem* pRet = HasTextItem(nWhich);
822  return pRet ? *pRet : rNd.SwContentNode::GetAttr(nWhich);
823 }
824 
825 void WW8AttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 /*nPos*/, const SwFormatRuby& rRuby )
826 {
827  WW8Ruby aWW8Ruby(rNode, rRuby, GetExport());
828  OUString aStr( FieldString( ww::eEQ ) );
829  aStr += "\\* jc";
830  aStr += OUString::number(aWW8Ruby.GetJC());
831 
832 
833  aStr += " \\* \"Font:";
834  aStr += aWW8Ruby.GetFontFamily();
835  aStr += "\" \\* hps";
836  aStr += OUString::number((aWW8Ruby.GetRubyHeight() + 5) / 10);
837  aStr += " \\o";
838  if (aWW8Ruby.GetDirective())
839  {
840  aStr += "\\a" + OUString(aWW8Ruby.GetDirective());
841  }
842  aStr += "(\\s\\up ";
843 
844  aStr += OUString::number((aWW8Ruby.GetBaseHeight() + 10) / 20 - 1);
845  aStr += "(";
846  aStr += rRuby.GetText();
847  aStr += ")";
848 
849  // The parameter separator depends on the FIB.lid
850  if ( m_rWW8Export.pFib->getNumDecimalSep() == '.' )
851  aStr += ",";
852  else
853  aStr += ";";
854 
855  m_rWW8Export.OutputField( nullptr, ww::eEQ, aStr,
857 }
858 
859 void WW8AttributeOutput::EndRuby(const SwTextNode& /*rNode*/, sal_Int32 /*nPos*/)
860 {
861  m_rWW8Export.WriteChar( ')' );
863 }
864 
865 /*#i15387# Better ideas welcome*/
866 static OUString &TruncateBookmark( OUString &rRet )
867 {
868  if ( rRet.getLength() > 40 )
869  rRet = rRet.copy( 0, 40 );
870  OSL_ENSURE( rRet.getLength() <= 40, "Word cannot have bookmarks longer than 40 chars" );
871  return rRet;
872 }
873 
874 OUString AttributeOutputBase::ConvertURL( const OUString& rUrl, bool bAbsoluteOut )
875 {
876  OUString sURL = rUrl;
877 
878  INetURLObject anAbsoluteParent(m_sBaseURL);
879  OUString sConvertedParent = INetURLObject::GetScheme( anAbsoluteParent.GetProtocol() ) + anAbsoluteParent.GetURLPath();
880  OUString sParentPath = sConvertedParent.isEmpty() ? m_sBaseURL : sConvertedParent;
881 
882  if ( bAbsoluteOut )
883  {
884  INetURLObject anAbsoluteNew;
885 
886  if ( anAbsoluteParent.GetNewAbsURL( rUrl, &anAbsoluteNew ) )
887  sURL = anAbsoluteNew.GetMainURL( INetURLObject::DecodeMechanism::NONE );
888  }
889  else
890  {
891  OUString sToConvert = rUrl.replaceAll( "\\", "/" );
892  INetURLObject aURL( sToConvert );
893  sToConvert = INetURLObject::GetScheme( aURL.GetProtocol() ) + aURL.GetURLPath();
895  if ( !sRelative.isEmpty() )
896  sURL = sRelative;
897  }
898 
899  return sURL;
900 }
901 
902 bool AttributeOutputBase::AnalyzeURL( const OUString& rUrl, const OUString& /*rTarget*/, OUString* pLinkURL, OUString* pMark )
903 {
904  bool bBookMarkOnly = false;
905 
906  OUString sMark;
907  OUString sURL;
908 
909  if ( rUrl.getLength() > 1 && rUrl[0] == '#' )
910  {
911  sMark = BookmarkToWriter( rUrl.copy(1) );
912 
913  const sal_Int32 nPos = sMark.lastIndexOf( cMarkSeparator );
914 
915  const OUString sRefType(nPos>=0 && nPos+1<sMark.getLength() ?
916  sMark.copy(nPos+1).replaceAll(" ", "") :
917  OUString());
918 
919  // #i21465# Only interested in outline references
920  if ( sRefType == "outline" )
921  {
922  OUString sLink = sMark.copy(0, nPos);
923  for ( const auto& rBookmarkPair : GetExport().m_aImplicitBookmarks )
924  {
925  if ( rBookmarkPair.first == sLink )
926  {
927  sMark = "_toc" + OUString::number( rBookmarkPair.second );
928  }
929  }
930  }
931  }
932  else
933  {
934  INetURLObject aURL( rUrl, INetProtocol::NotValid );
937  INetProtocol aProtocol = aURL.GetProtocol();
938 
939  if ( aProtocol == INetProtocol::File || aProtocol == INetProtocol::NotValid )
940  {
941  // INetProtocol::NotValid - may be a relative link
942  bool bExportRelative = m_aSaveOpt.IsSaveRelFSys();
943  sURL = ConvertURL( rUrl, !bExportRelative );
944  }
945  }
946 
947  if ( !sMark.isEmpty() && sURL.isEmpty() )
948  bBookMarkOnly = true;
949 
950  *pMark = sMark;
951  *pLinkURL = sURL;
952  return bBookMarkOnly;
953 }
954 
955 bool WW8AttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTarget, OUString* pLinkURL, OUString* pMark )
956 {
957  bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
958 
959  OUString sURL = *pLinkURL;
960 
961  if ( !sURL.isEmpty() )
963 
964  if ( bBookMarkOnly )
965  sURL = FieldString( ww::eHYPERLINK );
966  else
967  sURL = FieldString( ww::eHYPERLINK ) + "\"" + sURL + "\"";
968 
969  if ( !pMark->isEmpty() )
970  sURL += " \\l \"" + *pMark + "\"";
971 
972  if ( !rTarget.isEmpty() )
973  sURL += " \\n " + rTarget;
974 
975  *pLinkURL = sURL;
976 
977  return bBookMarkOnly;
978 }
979 
980 void WW8AttributeOutput::WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos )
981 {
982  m_aBookmarksOfParagraphStart.insert(std::pair<sal_Int32, OUString>(nFirstRunPos, rName));
983  m_aBookmarksOfParagraphEnd.insert(std::pair<sal_Int32, OUString>(nLastRunPos, rName));
984 }
985 
986 bool WW8AttributeOutput::StartURL( const OUString &rUrl, const OUString &rTarget )
987 {
988  INetURLObject aURL( rUrl );
989  OUString sURL;
990  OUString sMark;
991 
992  bool bBookMarkOnly = AnalyzeURL( rUrl, rTarget, &sURL, &sMark );
993 
995 
996  // write the reference to the "picture" structure
997  sal_uLong nDataStt = m_rWW8Export.pDataStrm->Tell();
998  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() );
999 
1000  // WinWord 2000 doesn't write this - so it's a temp solution by W97 ?
1001  m_rWW8Export.WriteChar( 0x01 );
1002 
1003  static sal_uInt8 aArr1[] = {
1004  0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
1005 
1006  0x06, 0x08, 0x01, // sprmCFData
1007  0x55, 0x08, 0x01, // sprmCFSpec
1008  0x02, 0x08, 0x01 // sprmCFFieldVanish
1009  };
1010  sal_uInt8* pDataAdr = aArr1 + 2;
1011  Set_UInt32( pDataAdr, nDataStt );
1012 
1013  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), sizeof( aArr1 ), aArr1 );
1014 
1016 
1017  // now write the picture structure
1018  sURL = aURL.GetURLNoMark();
1019 
1020  // Compare the URL written by AnalyzeURL with the original one to see if
1021  // the output URL is absolute or relative.
1022  OUString sRelativeURL;
1023  if ( !rUrl.isEmpty() )
1025  bool bAbsolute = sRelativeURL == rUrl;
1026 
1027  static sal_uInt8 aURLData1[] = {
1028  0,0,0,0, // len of struct
1029  0x44,0, // the start of "next" data
1030  0,0,0,0,0,0,0,0,0,0, // PIC-Structure!
1031  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
1032  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
1033  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
1034  0,0,0,0, // /
1035  };
1036  static sal_uInt8 MAGIC_A[] = {
1037  // start of "next" data
1038  0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
1039  0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
1040  };
1041 
1042  m_rWW8Export.pDataStrm->WriteBytes(aURLData1, sizeof(aURLData1));
1043  /* Write HFD Structure */
1044  sal_uInt8 nAnchor = 0x00;
1045  if ( !sMark.isEmpty() )
1046  nAnchor = 0x08;
1047  m_rWW8Export.pDataStrm->WriteUChar(nAnchor); // HFDBits
1048  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_A, sizeof(MAGIC_A)); //clsid
1049 
1050  /* Write Hyperlink Object see [MS-OSHARED] spec*/
1052  sal_uInt32 nFlag = bBookMarkOnly ? 0 : 0x01;
1053  if ( bAbsolute )
1054  nFlag |= 0x02;
1055  if ( !sMark.isEmpty() )
1056  nFlag |= 0x08;
1058 
1059  INetProtocol eProto = aURL.GetProtocol();
1060  if ( eProto == INetProtocol::File || eProto == INetProtocol::Smb )
1061  {
1062  // version 1 (for a document)
1063 
1064  static sal_uInt8 MAGIC_C[] = {
1065  0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1066  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
1067  0x00, 0x00
1068  };
1069 
1070  static sal_uInt8 MAGIC_D[] = {
1071  0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
1072  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1074  };
1075 
1076  // save the links to files as relative
1078  if ( eProto == INetProtocol::File && sURL.startsWith( "/" ) )
1079  sURL = aURL.PathToFileName();
1080 
1081  // special case for the absolute windows names
1082  // (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc')
1083  if (sURL.getLength()>=3)
1084  {
1085  const sal_Unicode aDrive = sURL[1];
1086  if ( sURL[0]=='/' && sURL[2]==':' &&
1087  ( (aDrive>='A' && aDrive<='Z' ) || (aDrive>='a' && aDrive<='z') ) )
1088  {
1089  sURL = sURL.copy(1).replaceAll("/", "\\");
1090  }
1091  }
1092 
1093  // n#261623 convert smb notation to '\\'
1094  const char pSmb[] = "smb://";
1095  if ( eProto == INetProtocol::Smb && sURL.startsWith( pSmb ) )
1096  {
1097  sURL = sURL.copy( sizeof(pSmb)-3 ).replaceAll( "/", "\\" );
1098  }
1099 
1100  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_C, sizeof(MAGIC_C));
1101  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sURL.getLength()+1 );
1103  RTL_TEXTENCODING_MS_1252 );
1104  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_D, sizeof(MAGIC_D));
1105 
1106  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.getLength() + 6 );
1107  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.getLength() );
1110  }
1111  else if ( eProto != INetProtocol::NotValid )
1112  {
1113  // version 2 (simple url)
1114  // and write some data to the data stream, but don't ask
1115  // what the data mean, except for the URL.
1116  // The First piece is the WW8_PIC structure.
1117  static sal_uInt8 MAGIC_B[] = {
1118  0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
1119  0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
1120  };
1121 
1122  m_rWW8Export.pDataStrm->WriteBytes(MAGIC_B, sizeof(MAGIC_B));
1123  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2 * ( sURL.getLength() + 1 ) );
1125  }
1126 
1127  if ( !sMark.isEmpty() )
1128  {
1129  SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sMark.getLength()+1 );
1131  }
1133  m_rWW8Export.pDataStrm->Tell() - nDataStt );
1134 
1135  return true;
1136 }
1137 
1139 {
1140  m_rWW8Export.OutputField( nullptr, ww::eHYPERLINK, OUString(), FieldFlags::Close );
1141 
1142  return true;
1143 }
1144 
1145 OUString BookmarkToWord(const OUString &rBookmark)
1146 {
1147  OUString sRet(INetURLObject::encode(
1148  rBookmark.replace(' ', '_'), // Spaces are prohibited in bookmark name
1150  INetURLObject::EncodeMechanism::All, RTL_TEXTENCODING_ASCII_US));
1151  // Unicode letters are allowed
1152  sRet = INetURLObject::decode(sRet, INetURLObject::DecodeMechanism::Unambiguous, RTL_TEXTENCODING_UTF8);
1153  return TruncateBookmark(sRet);
1154 }
1155 
1156 OUString BookmarkToWriter(const OUString &rBookmark)
1157 {
1158  return INetURLObject::decode(rBookmark,
1159  INetURLObject::DecodeMechanism::Unambiguous, RTL_TEXTENCODING_ASCII_US);
1160 }
1161 
1163 {
1164  if ( m_rExport.HasRefToObject( REF_SETREFATTR, &rAttr.GetRefName(), 0 ) )
1166  &rAttr.GetRefName(), 0 ));
1167 }
1168 
1169 void SwWW8AttrIter::SplitRun( sal_Int32 nSplitEndPos )
1170 {
1171  auto aIter = std::find_if(maCharRuns.begin(), maCharRuns.end(),
1172  [nSplitEndPos](const CharRunEntry& rCharRun) { return rCharRun.mnEndPos >= nSplitEndPos; });
1173  if (aIter == maCharRuns.end() || aIter->mnEndPos == nSplitEndPos)
1174  return;
1175 
1176  CharRunEntry aNewEntry = *aIter;
1177  aIter->mnEndPos = nSplitEndPos;
1178  maCharRuns.insert( ++aIter, aNewEntry);
1179  maCharRunIter = maCharRuns.begin();
1180  IterToCurrent();
1182 }
1183 
1184 void WW8AttributeOutput::FieldVanish( const OUString& rText, ww::eField /*eType*/ )
1185 {
1186  ww::bytes aItems;
1187  m_rWW8Export.GetCurrentItems( aItems );
1188 
1189  // sprmCFFieldVanish
1191  aItems.push_back( 1 );
1192 
1193  sal_uInt16 nStt_sprmCFSpec = aItems.size();
1194 
1195  // sprmCFSpec -- fSpec-Attribut true
1196  SwWW8Writer::InsUInt16( aItems, 0x855 );
1197  aItems.push_back( 1 );
1198 
1199  m_rWW8Export.WriteChar( '\x13' );
1200  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.size(),
1201  aItems.data() );
1202  m_rWW8Export.OutSwString(rText, 0, rText.getLength());
1203  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), nStt_sprmCFSpec,
1204  aItems.data() );
1205  m_rWW8Export.WriteChar( '\x15' );
1206  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.size(),
1207  aItems.data() );
1208 }
1209 
1210 void AttributeOutputBase::TOXMark( const SwTextNode& rNode, const SwTOXMark& rAttr )
1211 {
1212  // it's a field; so get the Text from the Node and build the field
1213  OUString sText;
1215 
1216  const SwTextTOXMark& rTextTOXMark = *rAttr.GetTextTOXMark();
1217  const sal_Int32* pTextEnd = rTextTOXMark.End();
1218  if ( pTextEnd ) // has range?
1219  {
1220  sText = rNode.GetExpandText(nullptr, rTextTOXMark.GetStart(),
1221  *pTextEnd - rTextTOXMark.GetStart() );
1222  }
1223  else
1224  sText = rAttr.GetAlternativeText();
1225 
1226  switch ( rAttr.GetTOXType()->GetType() )
1227  {
1228  case TOX_INDEX:
1229  eType = ww::eXE;
1230  if ( !rAttr.GetPrimaryKey().isEmpty() )
1231  {
1232  if ( !rAttr.GetSecondaryKey().isEmpty() )
1233  {
1234  sText = rAttr.GetSecondaryKey() + ":" + sText;
1235  }
1236 
1237  sText = rAttr.GetPrimaryKey() + ":" + sText;
1238  }
1239  sText = " XE \"" + sText + "\" ";
1240  break;
1241 
1242  case TOX_USER:
1243  sText += "\" \\f \"" + OUString(static_cast<sal_Char>( 'A' + GetExport( ).GetId( *rAttr.GetTOXType() ) ));
1244  [[fallthrough]];
1245  case TOX_CONTENT:
1246  {
1247  eType = ww::eTC;
1248  sText = " TC \"" + sText;
1249  sal_uInt16 nLvl = rAttr.GetLevel();
1250  if (nLvl > WW8ListManager::nMaxLevel)
1252 
1253  sText += "\" \\l " + OUString::number(nLvl) + " ";
1254  }
1255  break;
1256  default:
1257  OSL_ENSURE( false, "Unhandled option for toc export" );
1258  break;
1259  }
1260 
1261  if (!sText.isEmpty())
1262  FieldVanish( sText, eType );
1263 }
1264 
1265 int SwWW8AttrIter::OutAttrWithRange(const SwTextNode& rNode, sal_Int32 nPos)
1266 {
1267  int nRet = 0;
1268  if ( const SwpHints* pTextAttrs = rNd.GetpSwpHints() )
1269  {
1270  m_rExport.m_aCurrentCharPropStarts.push( nPos );
1271  const sal_Int32* pEnd;
1272  // first process ends of attributes with extent
1273  for (size_t i = 0; i < pTextAttrs->Count(); ++i)
1274  {
1275  const SwTextAttr* pHt = pTextAttrs->GetSortedByEnd(i);
1276  const SfxPoolItem* pItem = &pHt->GetAttr();
1277  switch ( pItem->Which() )
1278  {
1279  case RES_TXTATR_INETFMT:
1280  pEnd = pHt->End();
1281  if (nPos == *pEnd && nPos != pHt->GetStart())
1282  {
1283  if (m_rExport.AttrOutput().EndURL(nPos == rNd.Len()))
1284  --nRet;
1285  }
1286  break;
1287  case RES_TXTATR_REFMARK:
1288  pEnd = pHt->End();
1289  if (nullptr != pEnd && nPos == *pEnd && nPos != pHt->GetStart())
1290  {
1291  OutSwFormatRefMark(*static_cast<const SwFormatRefMark*>(pItem));
1292  --nRet;
1293  }
1294  break;
1295  case RES_TXTATR_CJK_RUBY:
1296  pEnd = pHt->End();
1297  if (nPos == *pEnd && nPos != pHt->GetStart())
1298  {
1299  m_rExport.AttrOutput().EndRuby(rNode, nPos);
1300  --nRet;
1301  }
1302  break;
1303  }
1304  if (nPos < pHt->GetAnyEnd())
1305  break; // sorted by end
1306  }
1307  for ( size_t i = 0; i < pTextAttrs->Count(); ++i )
1308  {
1309  const SwTextAttr* pHt = pTextAttrs->Get(i);
1310  const SfxPoolItem* pItem = &pHt->GetAttr();
1311  switch ( pItem->Which() )
1312  {
1313  case RES_TXTATR_INETFMT:
1314  if ( nPos == pHt->GetStart() )
1315  {
1316  const SwFormatINetFormat *rINet = static_cast< const SwFormatINetFormat* >( pItem );
1317  if ( m_rExport.AttrOutput().StartURL( rINet->GetValue(), rINet->GetTargetFrame() ) )
1318  ++nRet;
1319  }
1320  pEnd = pHt->End();
1321  if (nPos == *pEnd && nPos == pHt->GetStart())
1322  { // special case: empty must be handled here
1323  if (m_rExport.AttrOutput().EndURL(nPos == rNd.Len()))
1324  --nRet;
1325  }
1326  break;
1327  case RES_TXTATR_REFMARK:
1328  if ( nPos == pHt->GetStart() )
1329  {
1330  OutSwFormatRefMark( *static_cast< const SwFormatRefMark* >( pItem ) );
1331  ++nRet;
1332  }
1333  pEnd = pHt->End();
1334  if (nullptr != pEnd && nPos == *pEnd && nPos == pHt->GetStart())
1335  { // special case: empty TODO: is this possible or would empty one have pEnd null?
1336  OutSwFormatRefMark( *static_cast< const SwFormatRefMark* >( pItem ) );
1337  --nRet;
1338  }
1339  break;
1340  case RES_TXTATR_TOXMARK:
1341  if ( nPos == pHt->GetStart() )
1342  m_rExport.AttrOutput().TOXMark( rNd, *static_cast< const SwTOXMark* >( pItem ) );
1343  break;
1344  case RES_TXTATR_CJK_RUBY:
1345  if ( nPos == pHt->GetStart() )
1346  {
1347  m_rExport.AttrOutput().StartRuby( rNd, nPos, *static_cast< const SwFormatRuby* >( pItem ) );
1348  ++nRet;
1349  }
1350  pEnd = pHt->End();
1351  if (nPos == *pEnd && nPos == pHt->GetStart())
1352  { // special case: empty must be handled here
1353  m_rExport.AttrOutput().EndRuby( rNd, nPos );
1354  --nRet;
1355  }
1356  break;
1357  }
1358  if (nPos < pHt->GetStart())
1359  break; // sorted by start
1360  }
1361  m_rExport.m_aCurrentCharPropStarts.pop(); // HasTextItem only allowed in the above range
1362  }
1363  return nRet;
1364 }
1365 
1367 {
1368  // search next Redline
1371  {
1373  const SwPosition* pEnd = pRange->End();
1374  const SwPosition* pStart = pRange->Start();
1375  bool bBreak = true;
1376  // In word the paragraph end marker is a real character, in writer it is not.
1377  // Here we find out if the para end marker we will emit is affected by
1378  // redlining, in which case it must be included by the range of character
1379  // attributes that contains the redlining information.
1380  if (pEnd->nNode == rNd)
1381  {
1382  if (pEnd->nContent.GetIndex() == nEnd)
1383  {
1384  // This condition detects if the pseudo-char we will export
1385  // should be explicitly included by the redlining char
1386  // properties on this node because the redlining ends right
1387  // after it
1388  return true;
1389  }
1390  bBreak = false;
1391  }
1392  if (pStart->nNode == rNd)
1393  {
1394  if (pStart->nContent.GetIndex() == nEnd)
1395  {
1396  // This condition detects if the pseudo-char we will export
1397  // should be explicitly included by the redlining char
1398  // properties on this node because the redlining starts right
1399  // before it
1400  return true;
1401  }
1402  bBreak = false;
1403  }
1404  if (pStart->nNode.GetIndex()-1 == rNd.GetIndex())
1405  {
1406  if (pStart->nContent.GetIndex() == 0)
1407  {
1408  // This condition detects if the pseudo-char we will export
1409  // should be implicitly excluded by the redlining char
1410  // properties starting on the next node.
1411  return true;
1412  }
1413  bBreak = false;
1414  }
1415 
1416  if (bBreak)
1417  break;
1418  }
1419  return false;
1420 }
1421 
1423 {
1424  pCurRedline = nullptr;
1425 
1426  // ToDo : this is not the most ideal ... should start maybe from 'nCurRedlinePos'
1428  {
1429  const SwPosition* pCheckedStt = pRedl->Start();
1430 
1431  if( pCheckedStt->nNode == rNd )
1432  {
1433  // Maybe add here a check that also the start & end of the redline is the entire paragraph
1434 
1435  // Only return if this is a paragraph formatting redline
1436  if (pRedl->GetType() == RedlineType::ParagraphFormat)
1437  {
1438  // write data of this redline
1439  pCurRedline = pRedl;
1440  return &( pCurRedline->GetRedlineData() );
1441  }
1442  }
1443  }
1444  return nullptr;
1445 }
1446 
1448 {
1449  if( pCurRedline )
1450  {
1451  const SwPosition* pEnd = pCurRedline->End();
1452  if (!(pEnd->nNode == rNd && pEnd->nContent.GetIndex() <= nPos))
1453  {
1454  switch( pCurRedline->GetType() )
1455  {
1456  case RedlineType::Insert:
1457  case RedlineType::Delete:
1458  case RedlineType::Format:
1459  // write data of this redline
1460  return &( pCurRedline->GetRedlineData() );
1461  break;
1462  default:
1463  break;
1464  }
1465  }
1466  pCurRedline = nullptr;
1467  ++nCurRedlinePos;
1468  }
1469 
1470  assert(!pCurRedline);
1471  // search next Redline
1473  ++nCurRedlinePos )
1474  {
1476 
1477  const SwPosition* pStt = pRedl->Start();
1478  const SwPosition* pEnd = pStt == pRedl->GetPoint()
1479  ? pRedl->GetMark()
1480  : pRedl->GetPoint();
1481 
1482  if( pStt->nNode == rNd )
1483  {
1484  if( pStt->nContent.GetIndex() >= nPos )
1485  {
1486  if( pStt->nContent.GetIndex() == nPos )
1487  {
1488  switch( pRedl->GetType() )
1489  {
1490  case RedlineType::Insert:
1491  case RedlineType::Delete:
1492  case RedlineType::Format:
1493  // write data of this redline
1494  pCurRedline = pRedl;
1495  return &( pCurRedline->GetRedlineData() );
1496  break;
1497  default:
1498  break;
1499  }
1500  }
1501  break;
1502  }
1503  }
1504  else
1505  {
1506  break;
1507  }
1508 
1509  if( pEnd->nNode == rNd &&
1510  pEnd->nContent.GetIndex() < nPos )
1511  {
1512  pCurRedline = pRedl;
1513  break;
1514  }
1515  }
1516  return nullptr;
1517 }
1518 
1520 {
1521  const SwFrameFormat &rFormat = m_pCurrentPageDesc
1523  : m_pDoc->GetPageDesc( 0 ).GetMaster();
1524  return rFormat.GetFrameDir().GetValue();
1525 }
1526 
1528 {
1529  SvxFrameDirection nDir = SvxFrameDirection::Environment;
1530 
1531  if ( m_bOutPageDescs )
1532  nDir = GetCurrentPageDirection( );
1533  else if ( m_pOutFormatNode )
1534  {
1535  if ( m_bOutFlyFrameAttrs ) //frame
1536  {
1537  nDir = TrueFrameDirection( *static_cast< const SwFrameFormat * >(m_pOutFormatNode) );
1538  }
1539  else if ( dynamic_cast< const SwContentNode *>( m_pOutFormatNode ) != nullptr ) //paragraph
1540  {
1541  const SwContentNode *pNd = static_cast<const SwContentNode *>(m_pOutFormatNode);
1542  SwPosition aPos( *pNd );
1543  nDir = m_pDoc->GetTextDirection( aPos );
1544  }
1545  else if ( dynamic_cast< const SwTextFormatColl *>( m_pOutFormatNode ) != nullptr )
1546  {
1548  nDir = SvxFrameDirection::Horizontal_RL_TB;
1549  else
1550  nDir = SvxFrameDirection::Horizontal_LR_TB; //what else can we do :-(
1551  }
1552  }
1553 
1554  if ( nDir == SvxFrameDirection::Environment )
1555  {
1556  // fdo#44029 put direction right when the locale are RTL.
1558  nDir = SvxFrameDirection::Horizontal_RL_TB;
1559  else
1560  nDir = SvxFrameDirection::Horizontal_LR_TB; //Set something
1561  }
1562 
1563  return nDir;
1564 }
1565 
1567 {
1568  const SwFrameFormat *pFlyFormat = &rFlyFormat;
1569  const SvxFrameDirectionItem* pItem = nullptr;
1570  while ( pFlyFormat )
1571  {
1572  pItem = &pFlyFormat->GetFrameDir();
1573  if ( SvxFrameDirection::Environment == pItem->GetValue() )
1574  {
1575  pItem = nullptr;
1576  const SwFormatAnchor* pAnchor = &pFlyFormat->GetAnchor();
1577  if ((RndStdIds::FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
1578  pAnchor->GetContentAnchor() )
1579  {
1580  pFlyFormat = pAnchor->GetContentAnchor()->nNode.GetNode().GetFlyFormat();
1581  }
1582  else
1583  pFlyFormat = nullptr;
1584  }
1585  else
1586  pFlyFormat = nullptr;
1587  }
1588 
1589  SvxFrameDirection nRet;
1590  if ( pItem )
1591  nRet = pItem->GetValue();
1592  else
1593  nRet = GetCurrentPageDirection();
1594 
1595  OSL_ENSURE( nRet != SvxFrameDirection::Environment, "leaving with environment direction" );
1596  return nRet;
1597 }
1598 
1600 {
1601  const SwFrameFormat &rFormat = m_pCurrentPageDesc
1603  : m_pDoc->GetPageDesc(0).GetMaster();
1604 
1605  const SfxPoolItem* pItem = nullptr;
1606  //If not set, or "no fill", get real bg
1607  SfxItemState eState = rFormat.GetItemState(RES_BACKGROUND, true, &pItem);
1608 
1609  const SvxBrushItem* pRet = static_cast<const SvxBrushItem*>(pItem);
1610  if (SfxItemState::SET != eState || !pRet || (!pRet->GetGraphic() &&
1611  pRet->GetColor() == COL_TRANSPARENT))
1612  {
1613  pRet = &(DefaultItemGet<SvxBrushItem>(*m_pDoc,RES_BACKGROUND));
1614  }
1615  return pRet;
1616 }
1617 
1618 std::shared_ptr<SvxBrushItem> WW8Export::TrueFrameBgBrush(const SwFrameFormat &rFlyFormat) const
1619 {
1620  const SwFrameFormat *pFlyFormat = &rFlyFormat;
1621  const SvxBrushItem* pRet = nullptr;
1622 
1623  while (pFlyFormat)
1624  {
1625  //If not set, or "no fill", get real bg
1626  const SfxPoolItem* pItem = nullptr;
1627  SfxItemState eState =
1628  pFlyFormat->GetItemState(RES_BACKGROUND, true, &pItem);
1629  pRet = static_cast<const SvxBrushItem*>(pItem);
1630  if (SfxItemState::SET != eState || !pRet || (!pRet->GetGraphic() &&
1631  pRet->GetColor() == COL_TRANSPARENT))
1632  {
1633  pRet = nullptr;
1634  const SwFormatAnchor* pAnchor = &pFlyFormat->GetAnchor();
1635  if ((RndStdIds::FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
1636  pAnchor->GetContentAnchor())
1637  {
1638  pFlyFormat =
1639  pAnchor->GetContentAnchor()->nNode.GetNode().GetFlyFormat();
1640  }
1641  else
1642  pFlyFormat = nullptr;
1643  }
1644  else
1645  pFlyFormat = nullptr;
1646  }
1647 
1648  if (!pRet)
1649  pRet = GetCurrentPageBgBrush();
1650 
1651  const Color aTmpColor( COL_WHITE );
1652  std::shared_ptr<SvxBrushItem> aRet(std::make_shared<SvxBrushItem>(aTmpColor, RES_BACKGROUND));
1653 
1654  if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
1655  {
1656  aRet.reset(static_cast<SvxBrushItem*>(pRet->Clone()));
1657  }
1658 
1659  return aRet;
1660 }
1661 
1662 /*
1663 Convert characters that need to be converted, the basic replacements and the
1664 ridiculously complicated title case attribute mapping to hardcoded upper case
1665 because word doesn't have the feature
1666 */
1667 OUString SwWW8AttrIter::GetSnippet(const OUString &rStr, sal_Int32 nCurrentPos,
1668  sal_Int32 nLen) const
1669 {
1670  if (!nLen)
1671  return OUString();
1672 
1673  OUString aSnippet(rStr.copy(nCurrentPos, nLen));
1674  // 0x0a ( Hard Line Break ) -> 0x0b
1675  // 0xad ( soft hyphen ) -> 0x1f
1676  // 0x2011 ( hard hyphen ) -> 0x1e
1677  aSnippet = aSnippet.replace(0x0A, 0x0B);
1678  aSnippet = aSnippet.replace(CHAR_HARDHYPHEN, 0x1e);
1679  aSnippet = aSnippet.replace(CHAR_SOFTHYPHEN, 0x1f);
1680 
1681  // tdf#123703 revert import workaround for longer space characters in consecutive spaces
1682  sal_Int32 nPos;
1683  if ((nPos = aSnippet.indexOf(0x2006)) > -1)
1684  {
1685  const sal_Unicode aExtraSpace[5] = { 0x2006, 0x20, 0x2006, 0x20, 0 };
1686  const sal_Unicode aExtraSpace2[4] = { 0x20, 0x2006, 0x20, 0 };
1687  OUString sDoubleSpace(" ");
1688  aSnippet = aSnippet.replaceAll(aExtraSpace, sDoubleSpace, nPos)
1689  .replaceAll(aExtraSpace2, sDoubleSpace);
1690  }
1691 
1692  m_rExport.m_aCurrentCharPropStarts.push( nCurrentPos );
1693  const SfxPoolItem &rItem = GetItem(RES_CHRATR_CASEMAP);
1694 
1695  if (SvxCaseMap::Capitalize == static_cast<const SvxCaseMapItem&>(rItem).GetValue())
1696  {
1697  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
1698  sal_uInt16 nScriptType = g_pBreakIt->GetBreakIter()->getScriptType(aSnippet, 0);
1699 
1700  LanguageType nLanguage;
1701  switch (nScriptType)
1702  {
1703  case i18n::ScriptType::ASIAN:
1704  nLanguage = static_cast<const SvxLanguageItem&>(GetItem(RES_CHRATR_CJK_LANGUAGE)).GetLanguage();
1705  break;
1706  case i18n::ScriptType::COMPLEX:
1707  nLanguage = static_cast<const SvxLanguageItem&>(GetItem(RES_CHRATR_CTL_LANGUAGE)).GetLanguage();
1708  break;
1709  case i18n::ScriptType::LATIN:
1710  default:
1711  nLanguage = static_cast<const SvxLanguageItem&>(GetItem(RES_CHRATR_LANGUAGE)).GetLanguage();
1712  break;
1713  }
1714 
1715  SvxFont aFontHelper;
1716  aFontHelper.SetCaseMap(SvxCaseMap::Capitalize);
1717  aFontHelper.SetLanguage(nLanguage);
1718  aSnippet = aFontHelper.CalcCaseMap(aSnippet);
1719 
1720  //If we weren't at the begin of a word undo the case change.
1721  //not done before doing the casemap because the sequence might start
1722  //with whitespace
1723  if (!g_pBreakIt->GetBreakIter()->isBeginWord(
1724  rStr, nCurrentPos, g_pBreakIt->GetLocale(nLanguage),
1725  i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
1726  {
1727  aSnippet = OUStringLiteral1(rStr[nCurrentPos]) + aSnippet.copy(1);
1728  }
1729  }
1731 
1732  return aSnippet;
1733 }
1734 
1742 {
1745  while( nPos < nMax )
1746  {
1747  const SwRangeRedline* pRedl = rExport.m_pDoc->getIDocumentRedlineAccess().GetRedlineTable()[ nPos++ ];
1748  const SwPosition* pStt = pRedl->Start();
1749  const SwPosition* pEnd = pStt == pRedl->GetPoint()
1750  ? pRedl->GetMark()
1751  : pRedl->GetPoint();
1752  // Looking for deletions, which ends in current pTextNode
1753  if( RedlineType::Delete == pRedl->GetRedlineData().GetType() &&
1754  pEnd->nNode == *pTextNode && pStt->nNode != *pTextNode &&
1755  pStt->nNode.GetNode().IsTextNode() )
1756  {
1757  pTextNode = pStt->nNode.GetNode().GetTextNode();
1758  nMax = nPos;
1759  nPos = 0;
1760  }
1761  }
1762  return static_cast<SwTextFormatColl&>( pTextNode->GetAnyFormatColl() );
1763 }
1764 
1765 void WW8AttributeOutput::FormatDrop( const SwTextNode& rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle,
1767 {
1768  short nDropLines = rSwFormatDrop.GetLines();
1769  short nDistance = rSwFormatDrop.GetDistance();
1770  int rFontHeight, rDropHeight, rDropDescent;
1771 
1772  SVBT16 nSty;
1773  ShortToSVBT16( nStyle, nSty );
1774  m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nSty, nSty+2 ); // Style #
1775 
1776  m_rWW8Export.InsUInt16( NS_sprm::sprmPPc ); // Alignment (sprmPPc)
1777  m_rWW8Export.pO->push_back( 0x20 );
1778 
1779  m_rWW8Export.InsUInt16( NS_sprm::sprmPWr ); // Wrapping (sprmPWr)
1780  m_rWW8Export.pO->push_back( 0x02 );
1781 
1782  m_rWW8Export.InsUInt16( NS_sprm::sprmPDcs ); // Dropcap (sprmPDcs)
1783  int nDCS = ( nDropLines << 3 ) | 0x01;
1784  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
1785 
1786  m_rWW8Export.InsUInt16( NS_sprm::sprmPDxaFromText ); // Distance from text (sprmPDxaFromText)
1787  m_rWW8Export.InsUInt16( nDistance );
1788 
1789  if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
1790  {
1791  m_rWW8Export.InsUInt16( NS_sprm::sprmPDyaLine ); // Line spacing
1792  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
1793  m_rWW8Export.InsUInt16( 0 );
1794  }
1795 
1796  m_rWW8Export.WriteCR( pTextNodeInfoInner );
1797 
1798  if ( pTextNodeInfo.get() != nullptr )
1799  {
1800 #ifdef DBG_UTIL
1801  SAL_INFO( "sw.ww8", pTextNodeInfo->toString());
1802 #endif
1803  TableInfoCell( pTextNodeInfoInner );
1804  }
1805 
1806  m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
1807  m_rWW8Export.pO->clear();
1808 
1809  if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
1810  {
1811  const SwCharFormat *pSwCharFormat = rSwFormatDrop.GetCharFormat();
1812  if ( pSwCharFormat )
1813  {
1815  m_rWW8Export.InsUInt16( m_rWW8Export.GetId( pSwCharFormat ) );
1816  }
1817 
1818  m_rWW8Export.InsUInt16( NS_sprm::sprmCHpsPos ); // Lower the chars
1819  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
1820 
1821  m_rWW8Export.InsUInt16( NS_sprm::sprmCHps ); // Font Size
1822  m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
1823  }
1824 
1825  m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );
1826  m_rWW8Export.pO->clear();
1827 }
1828 
1829 sal_Int32 MSWordExportBase::GetNextPos( SwWW8AttrIter const * aAttrIter, const SwTextNode& rNode, sal_Int32 nCurrentPos )
1830 {
1831  // Get the bookmarks for the normal run
1832  const sal_Int32 nNextPos = aAttrIter->WhereNext();
1833  sal_Int32 nNextBookmark = nNextPos;
1834  sal_Int32 nNextAnnotationMark = nNextPos;
1835 
1836  if( nNextBookmark > nCurrentPos ) //no need to search for bookmarks otherwise (checked in UpdatePosition())
1837  {
1838  GetSortedBookmarks( rNode, nCurrentPos, nNextBookmark - nCurrentPos );
1839  NearestBookmark( nNextBookmark, nCurrentPos, false );
1840  GetSortedAnnotationMarks(*aAttrIter, nCurrentPos, nNextAnnotationMark - nCurrentPos);
1841  NearestAnnotationMark( nNextAnnotationMark, nCurrentPos, false );
1842  }
1843  return std::min( nNextPos, std::min( nNextBookmark, nNextAnnotationMark ) );
1844 }
1845 
1846 void MSWordExportBase::UpdatePosition( SwWW8AttrIter* aAttrIter, sal_Int32 nCurrentPos )
1847 {
1848  sal_Int32 nNextPos;
1849 
1850  // go to next attribute if no bookmark is found or if the bookmark is after the next attribute position
1851  // It may happened that the WhereNext() wasn't used in the previous increment because there was a
1852  // bookmark before it. Use that position before trying to find another one.
1853  bool bNextBookmark = NearestBookmark( nNextPos, nCurrentPos, true );
1854  if( nCurrentPos == aAttrIter->WhereNext() && ( !bNextBookmark || nNextPos > aAttrIter->WhereNext() ) )
1855  aAttrIter->NextPos();
1856 }
1857 
1858 bool MSWordExportBase::GetBookmarks( const SwTextNode& rNd, sal_Int32 nStt,
1859  sal_Int32 nEnd, IMarkVector& rArr )
1860 {
1861  IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
1862  sal_uLong nNd = rNd.GetIndex( );
1863 
1864  const sal_Int32 nMarks = pMarkAccess->getAllMarksCount();
1865  for ( sal_Int32 i = 0; i < nMarks; i++ )
1866  {
1867  IMark* pMark = pMarkAccess->getAllMarksBegin()[i];
1868 
1870  {
1871  continue;
1872  }
1873 
1874  // Only keep the bookmarks starting or ending in this node
1875  if ( pMark->GetMarkStart().nNode == nNd ||
1876  pMark->GetMarkEnd().nNode == nNd )
1877  {
1878  const sal_Int32 nBStart = pMark->GetMarkStart().nContent.GetIndex();
1879  const sal_Int32 nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
1880 
1881  // Keep only the bookmarks starting or ending in the snippet
1882  bool bIsStartOk = ( pMark->GetMarkStart().nNode == nNd ) && ( nBStart >= nStt ) && ( nBStart <= nEnd );
1883  bool bIsEndOk = ( pMark->GetMarkEnd().nNode == nNd ) && ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
1884 
1885  if ( bIsStartOk || bIsEndOk )
1886  {
1887  rArr.push_back( pMark );
1888  }
1889  }
1890  }
1891  return ( !rArr.empty() );
1892 }
1893 
1894 bool MSWordExportBase::GetAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nStt,
1895  sal_Int32 nEnd, IMarkVector& rArr )
1896 {
1897  IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
1898  sal_uLong nNd = rAttrs.GetNode().GetIndex();
1899 
1900  const sal_Int32 nMarks = pMarkAccess->getAnnotationMarksCount();
1901  for ( sal_Int32 i = 0; i < nMarks; i++ )
1902  {
1903  IMark* pMark = pMarkAccess->getAnnotationMarksBegin()[i];
1904 
1905  // Only keep the bookmarks starting or ending in this node
1906  if ( pMark->GetMarkStart().nNode == nNd ||
1907  pMark->GetMarkEnd().nNode == nNd )
1908  {
1909  const sal_Int32 nBStart = pMark->GetMarkStart().nContent.GetIndex();
1910  const sal_Int32 nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
1911 
1912  // Keep only the bookmarks starting or ending in the snippet
1913  bool bIsStartOk = ( pMark->GetMarkStart().nNode == nNd ) && ( nBStart >= nStt ) && ( nBStart <= nEnd );
1914  bool bIsEndOk = ( pMark->GetMarkEnd().nNode == nNd ) && ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
1915 
1916  // Annotation marks always have at least one character: the anchor
1917  // point of the comment field. In this case Word wants only the
1918  // comment field, so ignore the annotation mark itself.
1919  bool bSingleChar = pMark->GetMarkStart().nNode == pMark->GetMarkEnd().nNode && nBStart + 1 == nBEnd;
1920 
1921  if (bSingleChar)
1922  {
1923  if (rAttrs.HasFlysAt(nBStart))
1924  {
1925  // There is content (an at-char anchored frame) between the annotation mark
1926  // start/end, so still emit range start/end.
1927  bSingleChar = false;
1928  }
1929  }
1930 
1931  if ( ( bIsStartOk || bIsEndOk ) && !bSingleChar )
1932  {
1933  rArr.push_back( pMark );
1934  }
1935  }
1936  }
1937  return ( !rArr.empty() );
1938 }
1939 
1941 {
1942 public:
1943  bool operator() ( const IMark * pOneB, const IMark * pTwoB ) const
1944  {
1945  const sal_Int32 nOEnd = pOneB->GetMarkEnd().nContent.GetIndex();
1946  const sal_Int32 nTEnd = pTwoB->GetMarkEnd().nContent.GetIndex();
1947 
1948  return nOEnd < nTEnd;
1949  }
1950 };
1951 
1952 bool MSWordExportBase::NearestBookmark( sal_Int32& rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly )
1953 {
1954  bool bHasBookmark = false;
1955 
1956  if ( !m_rSortedBookmarksStart.empty() )
1957  {
1958  IMark* pMarkStart = m_rSortedBookmarksStart.front();
1959  const sal_Int32 nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
1960  if( !bNextPositionOnly || (nNext > nCurrentPos ))
1961  {
1962  rNearest = nNext;
1963  bHasBookmark = true;
1964  }
1965  }
1966 
1967  if ( !m_rSortedBookmarksEnd.empty() )
1968  {
1969  IMark* pMarkEnd = m_rSortedBookmarksEnd[0];
1970  const sal_Int32 nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
1971  if( !bNextPositionOnly || nNext > nCurrentPos )
1972  {
1973  if ( !bHasBookmark )
1974  rNearest = nNext;
1975  else
1976  rNearest = std::min( rNearest, nNext );
1977  bHasBookmark = true;
1978  }
1979  }
1980 
1981  return bHasBookmark;
1982 }
1983 
1984 void MSWordExportBase::NearestAnnotationMark( sal_Int32& rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly )
1985 {
1986  bool bHasAnnotationMark = false;
1987 
1988  if ( !m_rSortedAnnotationMarksStart.empty() )
1989  {
1990  IMark* pMarkStart = m_rSortedAnnotationMarksStart.front();
1991  const sal_Int32 nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
1992  if( !bNextPositionOnly || (nNext > nCurrentPos ))
1993  {
1994  rNearest = nNext;
1995  bHasAnnotationMark = true;
1996  }
1997  }
1998 
1999  if ( !m_rSortedAnnotationMarksEnd.empty() )
2000  {
2001  IMark* pMarkEnd = m_rSortedAnnotationMarksEnd[0];
2002  const sal_Int32 nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
2003  if( !bNextPositionOnly || nNext > nCurrentPos )
2004  {
2005  if ( !bHasAnnotationMark )
2006  rNearest = nNext;
2007  else
2008  rNearest = std::min( rNearest, nNext );
2009  }
2010  }
2011 }
2012 
2013 void MSWordExportBase::GetSortedAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nCurrentPos, sal_Int32 nLen )
2014 {
2015  IMarkVector aMarksStart;
2016  if (GetAnnotationMarks(rAttrs, nCurrentPos, nCurrentPos + nLen, aMarksStart))
2017  {
2018  IMarkVector aSortedEnd;
2019  IMarkVector aSortedStart;
2020  for ( IMark* pMark : aMarksStart )
2021  {
2022  // Remove the positions equal to the current pos
2023  const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
2024  const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
2025 
2026  const SwTextNode& rNode = rAttrs.GetNode();
2027  if ( nStart > nCurrentPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
2028  aSortedStart.push_back( pMark );
2029 
2030  if ( nEnd > nCurrentPos && nEnd <= ( nCurrentPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
2031  aSortedEnd.push_back( pMark );
2032  }
2033 
2034  // Sort the bookmarks by end position
2035  std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
2036 
2037  m_rSortedAnnotationMarksStart.swap( aSortedStart );
2038  m_rSortedAnnotationMarksEnd.swap( aSortedEnd );
2039  }
2040  else
2041  {
2043  m_rSortedAnnotationMarksEnd.clear( );
2044  }
2045 }
2046 
2047 void MSWordExportBase::GetSortedBookmarks( const SwTextNode& rNode, sal_Int32 nCurrentPos, sal_Int32 nLen )
2048 {
2049  IMarkVector aMarksStart;
2050  if ( GetBookmarks( rNode, nCurrentPos, nCurrentPos + nLen, aMarksStart ) )
2051  {
2052  IMarkVector aSortedEnd;
2053  IMarkVector aSortedStart;
2054  for ( IMark* pMark : aMarksStart )
2055  {
2056  // Remove the positions equal to the current pos
2057  const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
2058  const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
2059 
2060  if ( nStart > nCurrentPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
2061  aSortedStart.push_back( pMark );
2062 
2063  if ( nEnd > nCurrentPos && nEnd <= ( nCurrentPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
2064  aSortedEnd.push_back( pMark );
2065  }
2066 
2067  // Sort the bookmarks by end position
2068  std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
2069 
2070  m_rSortedBookmarksStart.swap( aSortedStart );
2071  m_rSortedBookmarksEnd.swap( aSortedEnd );
2072  }
2073  else
2074  {
2075  m_rSortedBookmarksStart.clear( );
2076  m_rSortedBookmarksEnd.clear( );
2077  }
2078 }
2079 
2081 {
2083  return false;
2084 
2085  const SwPageDesc * pPageDesc = rNd.FindPageDesc()->GetFollow();
2086 
2087  if (m_pCurrentPageDesc != pPageDesc)
2088  {
2090  {
2091  return true;
2092  }
2093  }
2094 
2095  return false;
2096 }
2097 
2099 {
2100  rNd.fillSoftPageBreakList( pList );
2101  pList.insert(0);
2102  pList.insert( rNd.GetText().getLength() );
2103  return pList.size() > 2 && NeedSectionBreak( rNd );
2104 }
2105 
2107 {
2108  SAL_INFO( "sw.ww8", "<OutWW8_SwTextNode>" );
2109 
2110  ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( m_pTableInfo->getTableNodeInfo( &rNode ) );
2111 
2112  //For i120928,identify the last node
2113  bool bLastCR = false;
2114  bool bExported = false;
2115  {
2116  SwNodeIndex aNextIdx(rNode,1);
2117  SwNodeIndex aLastIdx(rNode.GetNodes().GetEndOfContent());
2118  if (aNextIdx == aLastIdx)
2119  bLastCR = true;
2120  }
2121 
2122  // In order to make sure watermark is stored in 'header.xml', check nTextTyp.
2123  // if it is document.xml, don't write the tags (watermark should be only in the 'header')
2124  SwWW8AttrIter aWatermarkAttrIter( *this, rNode );
2125  if (( TXT_HDFT != m_nTextTyp) && aWatermarkAttrIter.IsWatermarkFrame())
2126  {
2127  return;
2128  }
2129 
2130  bool bFlyInTable = m_pParentFrame && IsInTable();
2131 
2132  SwTextFormatColl& rTextColl = lcl_getFormatCollection( *this, &rNode );
2133  if ( !bFlyInTable )
2134  m_nStyleBeforeFly = GetId( rTextColl );
2135 
2136  // nStyleBeforeFly may change when we recurse into another node, so we
2137  // have to remember it in nStyle
2138  sal_uInt16 nStyle = m_nStyleBeforeFly;
2139 
2140  SwWW8AttrIter aAttrIter( *this, rNode );
2141  rtl_TextEncoding eChrSet = aAttrIter.GetCharSet();
2142 
2143  if ( m_bStartTOX )
2144  {
2145  // ignore TOX header section
2146  const SwSectionNode* pSectNd = rNode.FindSectionNode();
2147  if ( pSectNd && TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
2148  {
2149  AttrOutput().StartTOX( pSectNd->GetSection() );
2150  m_aCurrentCharPropStarts.push( 0 );
2151  }
2152  }
2153 
2154  // Emulate: If 1-row table is marked as don't split, then set the row as don't split.
2155  if ( IsInTable() )
2156  {
2157  const SwTableNode* pTableNode = rNode.FindTableNode();
2158  if ( pTableNode )
2159  {
2160  const SwTable& rTable = pTableNode->GetTable();
2161  const bool bKeep = rTable.GetFrameFormat()->GetKeep().GetValue();
2162  const bool bDontSplit = !rTable.GetFrameFormat()->GetLayoutSplit().GetValue();
2163  // bKeep handles this a different way later on, so ignore now
2164  if ( !bKeep && bDontSplit && rTable.GetTabLines().size() == 1 )
2165  {
2166  // bDontSplit : set don't split once for the row
2167  // but only for non-complex tables
2168  const SwTableBox* pBox = rNode.GetTableBox();
2169  const SwTableLine* pLine = pBox ? pBox->GetUpper() : nullptr;
2170  if ( pLine && !pLine->GetUpper() )
2171  {
2172  // check if box is first in that line:
2173  if ( 0 == pLine->GetBoxPos( pBox ) && pBox->GetSttNd() )
2174  {
2175  // check if paragraph is first in that line:
2176  if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) )
2177  pLine->GetFrameFormat()->SetFormatAttr(SwFormatRowSplit(!bDontSplit));
2178  }
2179  }
2180  }
2181  }
2182  }
2183 
2184  SwSoftPageBreakList softBreakList;
2185  // Let's decide if we need to split the paragraph because of a section break
2186  bool bNeedParaSplit = NeedTextNodeSplit( rNode, softBreakList )
2187  && !IsInTable();
2188 
2189  auto aBreakIt = softBreakList.begin();
2190  // iterate through portions on different pages
2191  do
2192  {
2193  sal_Int32 nCurrentPos = *aBreakIt;
2194 
2195  if( softBreakList.size() > 1 ) // not for empty paragraph
2196  ++aBreakIt;
2197 
2198  AttrOutput().StartParagraph( pTextNodeInfo );
2199 
2200  const SwSection* pTOXSect = nullptr;
2201  if( m_bInWriteTOX )
2202  {
2203  // check for end of TOX
2204  SwNodeIndex aIdx( rNode, 1 );
2205  if( !aIdx.GetNode().IsTextNode() )
2206  {
2207  const SwSectionNode* pTOXSectNd = rNode.FindSectionNode();
2208  if ( pTOXSectNd )
2209  {
2210  pTOXSect = &pTOXSectNd->GetSection();
2211 
2212  const SwNode* pNxt = rNode.GetNodes().GoNext( &aIdx );
2213  if( pNxt && pNxt->FindSectionNode() == pTOXSectNd )
2214  pTOXSect = nullptr;
2215  }
2216  }
2217  }
2218 
2219  if ( aAttrIter.RequiresImplicitBookmark() )
2220  {
2221  OUString sBkmkName = "_toc" + OUString::number( rNode.GetIndex() );
2222  // Add a bookmark converted to a Word name.
2223  AppendBookmark( BookmarkToWord( sBkmkName ) );
2224  }
2225 
2226  // Call this before write out fields and runs
2227  AttrOutput().GenerateBookmarksForSequenceField(rNode, aAttrIter);
2228 
2229  const OUString& aStr( rNode.GetText() );
2230 
2231  sal_Int32 const nEnd = bNeedParaSplit ? *aBreakIt : aStr.getLength();
2232  bool bIncludeEndOfParaCRInRedlineProperties = false;
2233  sal_Int32 nOpenAttrWithRange = 0;
2234 
2235  ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner;
2236  if ( pTextNodeInfo.get() != nullptr )
2237  {
2238  pTextNodeInfoInner = pTextNodeInfo->getFirstInner();
2239  }
2240 
2241  do {
2242 
2243  const SwRedlineData* pRedlineData = aAttrIter.GetRunLevelRedline( nCurrentPos );
2244  FlyProcessingState nStateOfFlyFrame = FLY_PROCESSED;
2245  bool bPostponeWritingText = false ;
2246  OUString aSavedSnippet ;
2247 
2248  sal_Int32 nNextAttr = GetNextPos( &aAttrIter, rNode, nCurrentPos );
2249 
2250  // Skip un-exportable attributes.
2251  if (!aAttrIter.IsExportableAttr(nCurrentPos))
2252  {
2253  nCurrentPos = nNextAttr;
2254  UpdatePosition(&aAttrIter, nCurrentPos);
2255  eChrSet = aAttrIter.GetCharSet();
2256  continue;
2257  }
2258 
2259  // Is this the only run in this paragraph and it's empty?
2260  bool bSingleEmptyRun = nCurrentPos == 0 && nNextAttr == 0;
2261  AttrOutput().StartRun( pRedlineData, nCurrentPos, bSingleEmptyRun );
2262 
2263  if( nNextAttr > nEnd )
2264  nNextAttr = nEnd;
2265 
2266  if( m_nTextTyp == TXT_FTN || m_nTextTyp == TXT_EDN )
2267  {
2268  if( AttrOutput().FootnoteEndnoteRefTag() )
2269  {
2270  AttrOutput().EndRun( &rNode, nCurrentPos, nNextAttr == nEnd );
2271  AttrOutput().StartRun( pRedlineData, nCurrentPos, bSingleEmptyRun );
2272  }
2273  }
2274 
2275  /*
2276  1) If there is a text node and an overlapping anchor, then write them in two different
2277  runs and not as part of the same run.
2278  2) Ensure that it is a text node and not in a fly.
2279  3) If the anchor is associated with a text node with empty text then we ignore.
2280  */
2281  if( rNode.IsTextNode()
2282  && aStr != "\001" && !aStr.isEmpty()
2283  && !rNode.GetFlyFormat()
2284  && !(IsInTable() && !AllowPostponedTextInTable())
2285  && aAttrIter.IsAnchorLinkedToThisNode(rNode.GetIndex()) )
2286  {
2287  bPostponeWritingText = true ;
2288  }
2289 
2290  nStateOfFlyFrame = aAttrIter.OutFlys( nCurrentPos );
2291  AttrOutput().SetStateOfFlyFrame( nStateOfFlyFrame );
2292  AttrOutput().SetAnchorIsLinkedToNode( bPostponeWritingText && (FLY_POSTPONED != nStateOfFlyFrame) );
2293  // Append bookmarks in this range after flys, exclusive of final
2294  // position of this range
2295  AppendBookmarks( rNode, nCurrentPos, nNextAttr - nCurrentPos );
2296  AppendAnnotationMarks(aAttrIter, nCurrentPos, nNextAttr - nCurrentPos);
2297 
2298  // At the moment smarttags are only written for paragraphs, at the
2299  // beginning of the paragraph.
2300  if (nCurrentPos == 0)
2301  AppendSmartTags(rNode);
2302 
2303  bool bTextAtr = aAttrIter.IsTextAttr( nCurrentPos );
2304  nOpenAttrWithRange += aAttrIter.OutAttrWithRange( rNode, nCurrentPos );
2305 
2306  sal_Int32 nLen = nNextAttr - nCurrentPos;
2307  if ( !bTextAtr && nLen )
2308  {
2309  sal_Unicode ch = aStr[nCurrentPos];
2310  const sal_Int32 ofs = ( ch == CH_TXT_ATR_FIELDSTART || ch == CH_TXT_ATR_FIELDEND || ch == CH_TXT_ATR_FORMELEMENT? 1 : 0 );
2311 
2312  IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
2313  if ( ch == CH_TXT_ATR_FIELDSTART )
2314  {
2315  SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
2316  ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
2317  OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
2318 
2319  // Date field is exported as content control, not as a simple field
2320  if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE)
2321  {
2322  if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
2323  {
2324  OutputField( nullptr, lcl_getFieldId( pFieldmark ),
2325  lcl_getFieldCode( pFieldmark ),
2327  WriteFormData( *pFieldmark );
2328  }
2329  }
2330  else
2331  {
2332 
2333  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
2334  && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
2335  {
2336  AppendBookmark( pFieldmark->GetName() );
2337  }
2338  ww::eField eFieldId = lcl_getFieldId( pFieldmark );
2339  OUString sCode = lcl_getFieldCode( pFieldmark );
2340  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
2341  {
2342  IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
2343  if ( it != pFieldmark->GetParameters()->end() )
2344  {
2345  OUString sFieldId;
2346  it->second >>= sFieldId;
2347  eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
2348  }
2349 
2350  it = pFieldmark->GetParameters()->find( ODF_CODE_PARAM );
2351  if ( it != pFieldmark->GetParameters()->end() )
2352  {
2353  it->second >>= sCode;
2354  }
2355  }
2356 
2357  OutputField( nullptr, eFieldId, sCode, FieldFlags::Start | FieldFlags::CmdStart );
2358 
2359  if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMTEXT)
2360  WriteFormData( *pFieldmark );
2361  else if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
2362  WriteHyperlinkData( *pFieldmark );
2363  OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::CmdEnd );
2364 
2365  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
2366  {
2367  // Check for the presence of a linked OLE object
2368  IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_OLE_PARAM );
2369  if ( it != pFieldmark->GetParameters()->end() )
2370  {
2371  OUString sOleId;
2372  uno::Any aValue = it->second;
2373  aValue >>= sOleId;
2374  if ( !sOleId.isEmpty() )
2375  OutputLinkedOLE( sOleId );
2376  }
2377  }
2378  }
2379  }
2380  else if ( ch == CH_TXT_ATR_FIELDEND )
2381  {
2382  SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
2383  ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
2384 
2385  OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDEND??" );
2386 
2387  if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE)
2388  {
2389  if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
2390  {
2391  OutputField( nullptr, ww::eFORMDATE, OUString(), FieldFlags::Close );
2392  }
2393  }
2394  else
2395  {
2396  ww::eField eFieldId = lcl_getFieldId( pFieldmark );
2397  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
2398  {
2399  IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
2400  if ( it != pFieldmark->GetParameters()->end() )
2401  {
2402  OUString sFieldId;
2403  it->second >>= sFieldId;
2404  eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
2405  }
2406  }
2407 
2408  OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close );
2409 
2410  if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
2411  && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
2412  {
2413  AppendBookmark( pFieldmark->GetName() );
2414  }
2415  }
2416  }
2417  else if ( ch == CH_TXT_ATR_FORMELEMENT )
2418  {
2419  SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
2420  ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
2421 
2422  bool isDropdownOrCheckbox = pFieldmark && (pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN ||
2423  pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX );
2424  if ( isDropdownOrCheckbox )
2425  AppendBookmark( pFieldmark->GetName() );
2426  OutputField( nullptr, lcl_getFieldId( pFieldmark ),
2427  lcl_getFieldCode( pFieldmark ),
2429  if ( isDropdownOrCheckbox )
2430  WriteFormData( *pFieldmark );
2431  OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::Close );
2432  if ( isDropdownOrCheckbox )
2433  AppendBookmark( pFieldmark->GetName() );
2434  }
2435  nLen -= ofs;
2436 
2437  // if paragraph needs to be split, write only until split position
2438  assert(!bNeedParaSplit || nCurrentPos <= *aBreakIt);
2439  if( bNeedParaSplit && nCurrentPos + ofs + nLen > *aBreakIt)
2440  nLen = *aBreakIt - nCurrentPos - ofs;
2441  assert(0 <= nLen);
2442 
2443  OUString aSnippet( aAttrIter.GetSnippet( aStr, nCurrentPos + ofs, nLen ) );
2444  if ( ( m_nTextTyp == TXT_EDN || m_nTextTyp == TXT_FTN ) && nCurrentPos == 0 && nLen > 0 )
2445  {
2446  // Allow MSO to emulate LO footnote text starting at left margin - only meaningful with hanging indent
2447  sal_Int32 nFirstLineIndent=0;
2449  const SwTextNode* pTextNode( rNode.GetTextNode() );
2450  if ( pTextNode && pTextNode->GetAttr(aSet) )
2451  {
2452  const SvxLRSpaceItem* pLRSpace = aSet.GetItem<SvxLRSpaceItem>(RES_LR_SPACE);
2453  if ( pLRSpace )
2454  nFirstLineIndent = pLRSpace->GetTextFirstLineOfst();
2455  }
2456 
2457  // Insert tab for aesthetic purposes #i24762#
2458  if ( m_bAddFootnoteTab && nFirstLineIndent < 0 && aSnippet[0] != 0x09 )
2459  aSnippet = "\x09" + aSnippet;
2460  m_bAddFootnoteTab = false;
2461  }
2462 
2463  if ( bPostponeWritingText && ( FLY_POSTPONED != nStateOfFlyFrame ) )
2464  {
2465  bPostponeWritingText = true ;
2466  aSavedSnippet = aSnippet ;
2467  }
2468  else
2469  {
2470  bPostponeWritingText = false ;
2471  AttrOutput().RunText( aSnippet, eChrSet );
2472  }
2473  }
2474 
2475  if ( aAttrIter.IsDropCap( nNextAttr ) )
2476  AttrOutput().FormatDrop( rNode, aAttrIter.GetSwFormatDrop(), nStyle, pTextNodeInfo, pTextNodeInfoInner );
2477 
2478  // Only output character attributes if this is not a postponed text run.
2479  if (0 != nEnd && !(bPostponeWritingText && FLY_PROCESSED == nStateOfFlyFrame))
2480  {
2481  // Output the character attributes
2482  // #i51277# do this before writing flys at end of paragraph
2484  aAttrIter.OutAttr( nCurrentPos, false );
2485  AttrOutput().EndRunProperties( pRedlineData );
2486  }
2487 
2488  // At the end of line, output the attributes until the CR.
2489  // Exception: footnotes at the end of line
2490  if ( nNextAttr == nEnd )
2491  {
2492  OSL_ENSURE( nOpenAttrWithRange >= 0, "odd to see this happening, expected >= 0" );
2493  if ( !bTextAtr && nOpenAttrWithRange <= 0 )
2494  {
2495  if ( aAttrIter.IncludeEndOfParaCRInRedlineProperties( nEnd ) )
2496  bIncludeEndOfParaCRInRedlineProperties = true;
2497  else
2498  {
2499  // insert final graphic anchors if any before CR
2500  nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
2501  // insert final bookmarks if any before CR and after flys
2502  AppendBookmarks( rNode, nEnd, 1 );
2503  AppendAnnotationMarks(aAttrIter, nEnd, 1);
2504  if ( pTOXSect )
2505  {
2507  AttrOutput().EndTOX( *pTOXSect ,false);
2508  }
2509  //For i120928,the position of the bullet's graphic is at end of doc
2510  if (bLastCR && (!bExported))
2511  {
2512  ExportGrfBullet(rNode);
2513  bExported = true;
2514  }
2515 
2516  WriteCR( pTextNodeInfoInner );
2517  }
2518  }
2519  }
2520 
2521  if (0 == nEnd)
2522  {
2523  // Output the character attributes
2524  // do it after WriteCR for an empty paragraph (otherwise
2525  // WW8_WrFkp::Append throws SPRMs away...)
2527  aAttrIter.OutAttr( nCurrentPos, false );
2528  AttrOutput().EndRunProperties( pRedlineData );
2529  }
2530 
2531  // Exception: footnotes at the end of line
2532  if ( nNextAttr == nEnd )
2533  {
2534  OSL_ENSURE(nOpenAttrWithRange >= 0,
2535  "odd to see this happening, expected >= 0");
2536  bool bAttrWithRange = (nOpenAttrWithRange > 0);
2537  if ( nCurrentPos != nEnd )
2538  {
2539  nOpenAttrWithRange += aAttrIter.OutAttrWithRange( rNode, nEnd );
2540  OSL_ENSURE(nOpenAttrWithRange == 0,
2541  "odd to see this happening, expected 0");
2542  }
2543 
2544  // !bIncludeEndOfParaCRInRedlineProperties implies we have just
2545  // emitted a CR, in which case we want to pass force=true to
2546  // OutputFKP to ensure that an FKP entry for direct character
2547  // formatting is written even if empty, so that the next one will
2548  // start after the CR.
2549  AttrOutput().OutputFKP(!bIncludeEndOfParaCRInRedlineProperties);
2550 
2551  if (bTextAtr || bAttrWithRange || bIncludeEndOfParaCRInRedlineProperties)
2552  {
2553  // insert final graphic anchors if any before CR
2554  nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
2555  // insert final bookmarks if any before CR and after flys
2556  AppendBookmarks( rNode, nEnd, 1 );
2557  AppendAnnotationMarks(aAttrIter, nEnd, 1);
2558  WriteCR( pTextNodeInfoInner );
2559  // #i120928 - position of the bullet's graphic is at end of doc
2560  if (bLastCR && (!bExported))
2561  {
2562  ExportGrfBullet(rNode);
2563  bExported = true;
2564  }
2565 
2566  if ( pTOXSect )
2567  {
2569  AttrOutput().EndTOX( *pTOXSect );
2570  }
2571 
2572  if (bIncludeEndOfParaCRInRedlineProperties)
2573  {
2574  AttrOutput().Redline( aAttrIter.GetRunLevelRedline( nEnd ) );
2575  //If there was no redline property emitted, force adding
2576  //another entry for the CR so that in the case that this
2577  //has no redline, but the next para does, then this one is
2578  //not merged with the next
2579  AttrOutput().OutputFKP(true);
2580  }
2581  }
2582  }
2583 
2585 
2586  if( bPostponeWritingText && FLY_PROCESSED == nStateOfFlyFrame )
2587  {
2588  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2589  //write the postponed text run
2590  AttrOutput().StartRun( pRedlineData, nCurrentPos, bSingleEmptyRun );
2593  if (0 != nEnd)
2594  {
2596  aAttrIter.OutAttr( nCurrentPos, false );
2597  AttrOutput().EndRunProperties( pRedlineData );
2598  }
2599  AttrOutput().RunText( aSavedSnippet, eChrSet );
2600  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2601  }
2602  else if( bPostponeWritingText && !aSavedSnippet.isEmpty() )
2603  {
2604  //write the postponed text run
2605  AttrOutput().RunText( aSavedSnippet, eChrSet );
2606  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2607  }
2608  else
2609  AttrOutput().EndRun(&rNode, nCurrentPos, nNextAttr == nEnd);
2610 
2611  nCurrentPos = nNextAttr;
2612  UpdatePosition( &aAttrIter, nCurrentPos );
2613  eChrSet = aAttrIter.GetCharSet();
2614  }
2615  while ( nCurrentPos < nEnd );
2616 
2617  // if paragraph is split, put the section break between the parts
2618  if( bNeedParaSplit && *aBreakIt != rNode.GetText().getLength() )
2619  {
2620  SwNodeIndex aNextIndex( rNode, 1 );
2621  const SwNode& pNextNode = aNextIndex.GetNode();
2622  // if there is a next node, use its attributes to create the new
2623  // section
2624  if( pNextNode.IsTextNode() )
2625  {
2626  const SwTextNode& rNextNode = *static_cast<SwTextNode*>(
2627  &aNextIndex.GetNode() );
2628  OutputSectionBreaks(rNextNode.GetpSwAttrSet(), rNextNode);
2629  }
2630  else if (pNextNode.IsEndNode() )
2631  {
2632  // In this case the same paragraph holds the next page style
2633  // too.
2634  const SwPageDesc* pNextPageDesc = m_pCurrentPageDesc->GetFollow();
2635  assert(pNextPageDesc);
2636  PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc);
2637  }
2638  }
2639  else if (!bNeedParaSplit)
2640  {
2641  // else check if section break needed after the paragraph
2642  AttrOutput().SectionBreaks(rNode);
2643  }
2644 
2646 
2647  AttrOutput().ParagraphStyle( nStyle );
2648 
2649  if ( m_pParentFrame && IsInTable() ) // Fly-Attrs
2650  OutputFormat( m_pParentFrame->GetFrameFormat(), false, false, true );
2651 
2652  if ( pTextNodeInfo.get() != nullptr )
2653  {
2654 #ifdef DBG_UTIL
2655  SAL_INFO( "sw.ww8", pTextNodeInfo->toString());
2656 #endif
2657 
2658  AttrOutput().TableInfoCell( pTextNodeInfoInner );
2659  if (pTextNodeInfoInner->isFirstInTable())
2660  {
2661  const SwTable * pTable = pTextNodeInfoInner->getTable();
2662 
2663  const SwTableFormat* pTabFormat = pTable->GetFrameFormat();
2664  if (pTabFormat != nullptr)
2665  {
2666  if (pTabFormat->GetBreak().GetBreak() == SvxBreak::PageBefore)
2667  AttrOutput().PageBreakBefore(true);
2668  }
2669  }
2670  }
2671 
2672  if ( !bFlyInTable )
2673  {
2674  SfxItemSet* pTmpSet = nullptr;
2675  const sal_uInt8 nPrvNxtNd = rNode.HasPrevNextLayNode();
2676 
2677  if( (ND_HAS_PREV_LAYNODE|ND_HAS_NEXT_LAYNODE ) != nPrvNxtNd )
2678  {
2679  const SfxPoolItem* pItem;
2680  if( SfxItemState::SET == rNode.GetSwAttrSet().GetItemState(
2681  RES_UL_SPACE, true, &pItem ) &&
2682  ( ( !( ND_HAS_PREV_LAYNODE & nPrvNxtNd ) &&
2683  static_cast<const SvxULSpaceItem*>(pItem)->GetUpper()) ||
2684  ( !( ND_HAS_NEXT_LAYNODE & nPrvNxtNd ) &&
2685  static_cast<const SvxULSpaceItem*>(pItem)->GetLower()) ))
2686  {
2687  pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
2688  SvxULSpaceItem aUL( *static_cast<const SvxULSpaceItem*>(pItem) );
2689  // #i25901#- consider compatibility option
2691  {
2692  if( !(ND_HAS_PREV_LAYNODE & nPrvNxtNd ))
2693  aUL.SetUpper( 0 );
2694  }
2695  // #i25901# - consider compatibility option
2697  {
2698  if( !(ND_HAS_NEXT_LAYNODE & nPrvNxtNd ))
2699  aUL.SetLower( 0 );
2700  }
2701  pTmpSet->Put( aUL );
2702  }
2703  }
2704 
2705  const bool bParaRTL = aAttrIter.IsParaRTL();
2706 
2707  int nNumberLevel = -1;
2708  if (rNode.IsNumbered())
2709  nNumberLevel = rNode.GetActualListLevel();
2710  if (nNumberLevel >= 0 && nNumberLevel < MAXLEVEL)
2711  {
2712  const SwNumRule* pRule = rNode.GetNumRule();
2713  sal_uInt8 nLvl = static_cast< sal_uInt8 >(nNumberLevel);
2714  const SwNumFormat* pFormat = pRule->GetNumFormat( nLvl );
2715  if( !pFormat )
2716  pFormat = &pRule->Get( nLvl );
2717 
2718  if( !pTmpSet )
2719  pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
2720 
2721  SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*pTmpSet, RES_LR_SPACE));
2722  // #i86652#
2723  if ( pFormat->GetPositionAndSpaceMode() ==
2725  {
2726  aLR.SetTextLeft( aLR.GetTextLeft() + pFormat->GetAbsLSpace() );
2727  }
2728 
2729  if( rNode.IsNumbered() && rNode.IsCountedInList() )
2730  {
2731  // #i86652#
2732  if ( pFormat->GetPositionAndSpaceMode() ==
2734  {
2735  if (bParaRTL)
2736  aLR.SetTextFirstLineOfstValue(pFormat->GetAbsLSpace() - pFormat->GetFirstLineOffset()); //TODO: overflow
2737  else
2738  aLR.SetTextFirstLineOfst(GetWordFirstLineOffset(*pFormat));
2739  }
2740 
2741  // correct fix for issue i94187
2742  if (SfxItemState::SET !=
2743  pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
2744  {
2745  // List style set via paragraph style - then put it into the itemset.
2746  // This is needed to get list level and list id exported for
2747  // the paragraph.
2748  pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
2749 
2750  // Put indent values into the itemset in case that the list
2751  // style is applied via paragraph style and the list level
2752  // indent values are not applicable.
2753  if ( pFormat->GetPositionAndSpaceMode() ==
2756  {
2757  pTmpSet->Put( aLR );
2758  }
2759  }
2760  }
2761  else
2762  pTmpSet->ClearItem(RES_PARATR_NUMRULE);
2763 
2764  // #i86652#
2765  if ( pFormat->GetPositionAndSpaceMode() ==
2767  {
2768  pTmpSet->Put(aLR);
2769 
2770  //#i21847#
2771  SvxTabStopItem aItem(
2772  ItemGet<SvxTabStopItem>(*pTmpSet, RES_PARATR_TABSTOP));
2773  SvxTabStop aTabStop(pFormat->GetAbsLSpace());
2774  aItem.Insert(aTabStop);
2775  pTmpSet->Put(aItem);
2776 
2778  }
2779  }
2780 
2781  /*
2782  If a given para is using the SvxFrameDirection::Environment direction we
2783  cannot export that, if it's ltr then that's ok as that is word's
2784  default. Otherwise we must add a RTL attribute to our export list
2785  Only necessary if the ParaStyle doesn't define the direction.
2786  */
2787  const SvxFrameDirectionItem* pItem =
2789  if (
2790  (!pItem || pItem->GetValue() == SvxFrameDirection::Environment) &&
2791  rTextColl.GetFrameDir().GetValue() == SvxFrameDirection::Environment
2792  )
2793  {
2794  if ( !pTmpSet )
2795  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2796 
2797  if ( bParaRTL )
2798  pTmpSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_RL_TB, RES_FRAMEDIR));
2799  else
2800  pTmpSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB, RES_FRAMEDIR));
2801 
2802  const SvxAdjustItem* pAdjust = rNode.GetSwAttrSet().GetItem(RES_PARATR_ADJUST);
2803  if ( pAdjust && (pAdjust->GetAdjust() == SvxAdjust::Left || pAdjust->GetAdjust() == SvxAdjust::Right ) )
2804  pTmpSet->Put( *pAdjust, RES_PARATR_ADJUST );
2805  }
2806  // move code for handling of numbered,
2807  // but not counted paragraphs to this place. Otherwise, the paragraph
2808  // isn't exported as numbered, but not counted, if no other attribute
2809  // is found in <pTmpSet>
2810  // #i44815# adjust numbering/indents for numbered paragraphs
2811  // without number (NO_NUMLEVEL)
2812  // #i47013# need to check rNode.GetNumRule()!=NULL as well.
2813  if ( ! rNode.IsCountedInList() && rNode.GetNumRule()!=nullptr )
2814  {
2815  // WW8 does not know numbered paragraphs without number
2816  // (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export
2817  // the RES_PARATR_NUMRULE as list-id 0, which in WW8 means
2818  // no numbering. Here, we will adjust the indents to match
2819  // visually.
2820 
2821  if ( !pTmpSet )
2822  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2823 
2824  // create new LRSpace item, based on the current (if present)
2825  const SfxPoolItem* pPoolItem = nullptr;
2826  pTmpSet->GetItemState(RES_LR_SPACE, true, &pPoolItem);
2827  SvxLRSpaceItem aLRSpace(
2828  ( pPoolItem == nullptr )
2829  ? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE)
2830  : *static_cast<const SvxLRSpaceItem*>( pPoolItem ) );
2831 
2832  // new left margin = old left + label space
2833  const SwNumRule* pRule = rNode.GetNumRule();
2834  int nLevel = rNode.GetActualListLevel();
2835 
2836  if (nLevel < 0)
2837  nLevel = 0;
2838 
2839  if (nLevel >= MAXLEVEL)
2840  nLevel = MAXLEVEL - 1;
2841 
2842  const SwNumFormat& rNumFormat = pRule->Get( static_cast< sal_uInt16 >(nLevel) );
2843 
2844  // #i86652#
2845  if ( rNumFormat.GetPositionAndSpaceMode() ==
2847  {
2848  aLRSpace.SetTextLeft( aLRSpace.GetLeft() + rNumFormat.GetAbsLSpace() );
2849  }
2850  else
2851  {
2852  aLRSpace.SetTextLeft( aLRSpace.GetLeft() + rNumFormat.GetIndentAt() );
2853  }
2854 
2855  // new first line indent = 0
2856  // (first line indent is ignored for NO_NUMLEVEL)
2857  if (!bParaRTL)
2858  aLRSpace.SetTextFirstLineOfst( 0 );
2859 
2860  // put back the new item
2861  pTmpSet->Put( aLRSpace );
2862 
2863  // assure that numbering rule is in <pTmpSet>
2864  if (SfxItemState::SET != pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
2865  {
2866  pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
2867  }
2868  }
2869 
2870  // #i75457#
2871  // Export page break after attribute from paragraph style.
2872  // If page break attribute at the text node exist, an existing page
2873  // break after at the paragraph style hasn't got to be considered.
2874  if ( !rNode.GetpSwAttrSet() ||
2875  SfxItemState::SET != rNode.GetpSwAttrSet()->GetItemState(RES_BREAK, false) )
2876  {
2877  const SvxFormatBreakItem& rBreakAtParaStyle
2878  = ItemGet<SvxFormatBreakItem>(rNode.GetSwAttrSet(), RES_BREAK);
2879  if (rBreakAtParaStyle.GetBreak() == SvxBreak::PageAfter)
2880  {
2881  if ( !pTmpSet )
2882  {
2883  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2884  }
2885  pTmpSet->Put(rBreakAtParaStyle);
2886  }
2887  else if( pTmpSet )
2888  { // Even a pagedesc item is set, the break item can be set 'NONE',
2889  // this has to be overruled.
2890  const SwFormatPageDesc& rPageDescAtParaStyle =
2891  ItemGet<SwFormatPageDesc>( rNode, RES_PAGEDESC );
2892  if( rPageDescAtParaStyle.KnowsPageDesc() )
2893  pTmpSet->ClearItem( RES_BREAK );
2894  }
2895  }
2896 
2897  // #i76520# Emulate non-splitting tables
2898  if ( IsInTable() )
2899  {
2900  const SwTableNode* pTableNode = rNode.FindTableNode();
2901 
2902  if ( pTableNode )
2903  {
2904  const SwTable& rTable = pTableNode->GetTable();
2905  const SvxFormatKeepItem& rKeep = rTable.GetFrameFormat()->GetKeep();
2906  const bool bKeep = rKeep.GetValue();
2907  const bool bDontSplit = !(bKeep ||
2908  rTable.GetFrameFormat()->GetLayoutSplit().GetValue());
2909 
2910  if ( bKeep || bDontSplit )
2911  {
2912  // bKeep: set keep at first paragraphs in all lines
2913  // bDontSplit : set keep at first paragraphs in all lines except from last line
2914  // but only for non-complex tables
2915  const SwTableBox* pBox = rNode.GetTableBox();
2916  const SwTableLine* pLine = pBox ? pBox->GetUpper() : nullptr;
2917 
2918  if ( pLine && !pLine->GetUpper() )
2919  {
2920  // check if box is first in that line:
2921  if ( 0 == pLine->GetBoxPos( pBox ) && pBox->GetSttNd() )
2922  {
2923  // check if paragraph is first in that line:
2924  if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) )
2925  {
2926  bool bSetAtPara = false;
2927  if ( bKeep )
2928  bSetAtPara = true;
2929  else if ( bDontSplit )
2930  {
2931  // check if pLine isn't last line in table
2932  if ( rTable.GetTabLines().size() - rTable.GetTabLines().GetPos( pLine ) != 1 )
2933  bSetAtPara = true;
2934  }
2935 
2936  if ( bSetAtPara )
2937  {
2938  if ( !pTmpSet )
2939  pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
2940 
2941  const SvxFormatKeepItem aKeepItem( true, RES_KEEP );
2942  pTmpSet->Put( aKeepItem );
2943  }
2944  }
2945  }
2946  }
2947  }
2948  }
2949  }
2950 
2951  const SfxItemSet* pNewSet = pTmpSet ? pTmpSet : rNode.GetpSwAttrSet();
2952  if( pNewSet )
2953  { // Para-Attrs
2954  m_pStyAttr = &rNode.GetAnyFormatColl().GetAttrSet();
2955 
2956  const SwModify* pOldMod = m_pOutFormatNode;
2957  m_pOutFormatNode = &rNode;
2958 
2959  // Pap-Attrs, so script is not necessary
2960  OutputItemSet( *pNewSet, true, false, i18n::ScriptType::LATIN, false);
2961 
2962  m_pStyAttr = nullptr;
2963  m_pOutFormatNode = pOldMod;
2964 
2965  if( pNewSet != rNode.GetpSwAttrSet() )
2966  delete pNewSet;
2967  }
2968  }
2969 
2970  // The formatting of the paragraph marker has two sources:
2971  // 1) If there are hints at the end of the paragraph, then use that.
2972  // 2) Else use the RES_CHRATR_BEGIN..RES_TXTATR_END range of the paragraph
2973  // properties.
2974  //
2975  // Exception: if there is a character style hint at the end of the
2976  // paragraph only, then still go with 2), as RES_TXTATR_CHARFMT is always
2977  // set as a hint.
2979  bool bCharFormatOnly = true;
2980  if(const SwpHints* pTextAttrs = rNode.GetpSwpHints())
2981  {
2982  for( size_t i = 0; i < pTextAttrs->Count(); ++i )
2983  {
2984  const SwTextAttr* pHt = pTextAttrs->Get(i);
2985  const sal_Int32 startPos = pHt->GetStart(); // first Attr characters
2986  const sal_Int32* endPos = pHt->End(); // end Attr characters
2987  // Check if these attributes are for the last character in the paragraph
2988  // - which means the paragraph marker. If a paragraph has 7 characters,
2989  // then properties on character 8 are for the paragraph marker
2990  if( endPos && (startPos == *endPos ) && (*endPos == rNode.GetText().getLength()) )
2991  {
2992  SAL_INFO( "sw.ww8", startPos << "startPos == endPos" << *endPos);
2993  sal_uInt16 nWhich = pHt->GetAttr().Which();
2994  SAL_INFO( "sw.ww8", "nWhich" << nWhich);
2995  if (nWhich == RES_TXTATR_AUTOFMT || nWhich == RES_TXTATR_CHARFMT)
2996  aParagraphMarkerProperties.Put(pHt->GetAttr());
2997  if (nWhich != RES_TXTATR_CHARFMT)
2998  bCharFormatOnly = false;
2999  }
3000  }
3001  }
3002  if (rNode.GetpSwAttrSet() && bCharFormatOnly)
3003  {
3004  aParagraphMarkerProperties.Put(*rNode.GetpSwAttrSet());
3005  }
3006  const SwRedlineData* pRedlineParagraphMarkerDelete = AttrOutput().GetParagraphMarkerRedline( rNode, RedlineType::Delete );
3007  const SwRedlineData* pRedlineParagraphMarkerInsert = AttrOutput().GetParagraphMarkerRedline( rNode, RedlineType::Insert );
3008  const SwRedlineData* pParagraphRedlineData = aAttrIter.GetParagraphLevelRedline( );
3009  AttrOutput().EndParagraphProperties(aParagraphMarkerProperties, pParagraphRedlineData, pRedlineParagraphMarkerDelete, pRedlineParagraphMarkerInsert);
3010 
3011  AttrOutput().EndParagraph( pTextNodeInfoInner );
3012  }while(*aBreakIt != rNode.GetText().getLength() && bNeedParaSplit );
3013 
3014  SAL_INFO( "sw.ww8", "</OutWW8_SwTextNode>" );
3015 }
3016 
3017 // Tables
3018 
3020 {
3021  m_rWW8Export.WriteStringAsPara( OUString() );
3022 }
3023 
3025 {
3026  bool bRet = false;
3027  const SfxPoolItem* pI;
3028  if( pSet)
3029  {
3030  bool bNoPageBreak = false;
3031  if ( SfxItemState::SET != pSet->GetItemState(RES_PAGEDESC, true, &pI)
3032  || nullptr == static_cast<const SwFormatPageDesc*>(pI)->GetPageDesc() )
3033  {
3034  bNoPageBreak = true;
3035  }
3036 
3037  if (bNoPageBreak)
3038  {
3039  if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, true, &pI))
3040  {
3041  SvxBreak eBreak = static_cast<const SvxFormatBreakItem*>(pI)->GetBreak();
3042  switch (eBreak)
3043  {
3044  case SvxBreak::PageBefore:
3045  case SvxBreak::PageAfter:
3046  bNoPageBreak = false;
3047  break;
3048  default:
3049  break;
3050  }
3051  }
3052  }
3053  bRet = bNoPageBreak;
3054  }
3055  return bRet;
3056 }
3057 
3059 {
3060  const SwSection& rSection = rSectionNode.GetSection();
3061 
3062  SwNodeIndex aIdx( rSectionNode, 1 );
3063  const SwNode& rNd = aIdx.GetNode();
3064  if ( !rNd.IsSectionNode() && !IsInTable()
3065  && rSection.GetType() != TOX_CONTENT_SECTION && rSection.GetType() != TOX_HEADER_SECTION) //No sections in table
3066  {
3067  // if the first Node inside the section has an own
3068  // PageDesc or PageBreak attribute, then don't write
3069  // here the section break
3070  sal_uLong nRstLnNum = 0;
3071  const SfxItemSet* pSet;
3072  if ( rNd.IsContentNode() )
3073  {
3074  pSet = &rNd.GetContentNode()->GetSwAttrSet();
3075  nRstLnNum = pSet->Get( RES_LINENUMBER ).GetStartValue();
3076  }
3077  else
3078  pSet = nullptr;
3079 
3080  if ( pSet && NoPageBreakSection( pSet ) )
3081  pSet = nullptr;
3082  else
3083  AttrOutput().SectionBreaks( rSectionNode );
3084 
3085  if ( !pSet )
3086  {
3087  // new Section with no own PageDesc/-Break
3088  // -> write follow section break;
3089  const SwSectionFormat* pFormat = rSection.GetFormat();
3090  ReplaceCr( msword::PageBreak ); // Indicator for Page/Section-Break
3091 
3092  // Get the page in use at the top of this section
3093  const SwPageDesc *pCurrent = SwPageDesc::GetPageDescOfNode(rNd);
3094  if (!pCurrent)
3095  pCurrent = m_pCurrentPageDesc;
3096 
3097  AppendSection( pCurrent, pFormat, nRstLnNum );
3098  }
3099  }
3100  if ( TOX_CONTENT_SECTION == rSection.GetType() )
3101  {
3102  m_bStartTOX = true;
3103  UpdateTocSectionNodeProperties(rSectionNode);
3104  }
3105 }
3106 
3107 // tdf#121561: During export of the ODT file with TOC inside into DOCX format,
3108 // the TOC title is being exported as regular paragraph. We should surround it
3109 // with <w:sdt><w:sdtPr><w:sdtContent> to make it (TOC title) recognizable
3110 // by MS Word as part of the TOC.
3112 {
3113  // check section type
3114  {
3115  const SwSection& rSection = rSectionNode.GetSection();
3116  if (TOX_CONTENT_SECTION != rSection.GetType())
3117  return;
3118 
3119  const SwTOXBase* pTOX = rSection.GetTOXBase();
3120  if (pTOX)
3121  {
3122  TOXTypes type = pTOX->GetType();
3123  if (type != TOXTypes::TOX_CONTENT)
3124  return;
3125  }
3126  }
3127 
3128  // get section node, skip toc-header node
3129  const SwSectionNode* pSectNd = &rSectionNode;
3130  {
3131  SwNodeIndex aIdxNext( *pSectNd, 1 );
3132  const SwNode& rNdNext = aIdxNext.GetNode();
3133 
3134  if (rNdNext.IsSectionNode())
3135  {
3136  const SwSectionNode* pSectNdNext = static_cast<const SwSectionNode*>(&rNdNext);
3137  if (TOX_HEADER_SECTION == pSectNdNext->GetSection().GetType() &&
3138  pSectNdNext->StartOfSectionNode()->IsSectionNode())
3139  {
3140  pSectNd = pSectNdNext;
3141  }
3142  }
3143  }
3144 
3145  // get node of the first paragraph inside TOC
3146  SwNodeIndex aIdxNext( *pSectNd, 1 );
3147  const SwNode& rNdTocPara = aIdxNext.GetNode();
3148  const SwContentNode* pNode = rNdTocPara.GetContentNode();
3149  if (!pNode)
3150  return;
3151 
3152  // put required flags into grab bag of the first node in TOC
3153  {
3154  uno::Sequence<beans::PropertyValue> aDocPropertyValues(comphelper::InitPropertySequence(
3155  {
3156  {"ooxml:CT_SdtDocPart_docPartGallery", uno::makeAny(OUString("Table of Contents"))},
3157  {"ooxml:CT_SdtDocPart_docPartUnique", uno::makeAny(OUString("true"))},
3158  }));
3159 
3160  uno::Sequence<beans::PropertyValue> aSdtPrPropertyValues(comphelper::InitPropertySequence(
3161  {
3162  {"ooxml:CT_SdtPr_docPartObj", uno::makeAny(aDocPropertyValues)},
3163  }));
3164 
3166  aGrabBag.GetGrabBag()["SdtPr"] <<= aSdtPrPropertyValues;
3167 
3168  // create temp attr set
3169  SwAttrSet aSet(pNode->GetSwAttrSet());
3170  aSet.Put(aGrabBag);
3171 
3172  // set new attr to node
3173  const_cast<SwContentNode*>(pNode)->SetAttr(aSet);
3174  }
3175 
3176  // set flag for the next node after TOC
3177  // in order to indicate that std area has been finished
3178  // see, DomainMapper::lcl_startParagraphGroup() for the same functionality during load
3179  {
3180  SwNodeIndex aEndTocNext( *rSectionNode.EndOfSectionNode(), 1 );
3181  const SwNode& rEndTocNextNode = aEndTocNext.GetNode();
3182  const SwContentNode* pNodeAfterToc = rEndTocNextNode.GetContentNode();
3183  if (pNodeAfterToc)
3184  {
3186  aGrabBag.GetGrabBag()["ParaSdtEndBefore"] <<= true;
3187 
3188  // create temp attr set
3189  SwAttrSet aSet(pNodeAfterToc->GetSwAttrSet());
3190  aSet.Put(aGrabBag);
3191 
3192  // set new attr to node
3193  const_cast<SwContentNode*>(pNodeAfterToc)->SetAttr(aSet);
3194  }
3195  }
3196 }
3197 
3198 void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFormat* pFormat, sal_uLong nLnNum )
3199 {
3200  pSepx->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc, pFormat, nLnNum);
3201 }
3202 
3203 // Flys
3204 
3205 void WW8AttributeOutput::OutputFlyFrame_Impl( const ww8::Frame& rFormat, const Point& rNdTopLeft )
3206 {
3207  const SwFrameFormat &rFrameFormat = rFormat.GetFrameFormat();
3208  const SwFormatAnchor& rAnch = rFrameFormat.GetAnchor();
3209 
3210  bool bUseEscher = true;
3211 
3212  if (rFormat.IsInline())
3213  {
3215  bUseEscher = eType != ww8::Frame::eGraphic && eType != ww8::Frame::eOle;
3216 
3217  /*
3218  A special case for converting some inline form controls to form fields
3219  when in winword 8+ mode
3220  */
3221  if (bUseEscher && (eType == ww8::Frame::eFormControl))
3222  {
3223  if ( m_rWW8Export.MiserableFormFieldExportHack( rFrameFormat ) )
3224  return ;
3225  }
3226  }
3227 
3228  if (bUseEscher)
3229  {
3230  // write as escher
3231  m_rWW8Export.AppendFlyInFlys(rFormat, rNdTopLeft);
3232  }
3233  else
3234  {
3235  bool bDone = false;
3236 
3237  // Fetch from node and last node the position in the section
3238  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
3239 
3240  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
3241  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
3242 
3243  if( nStt >= nEnd ) // no range, hence no valid node
3244  return;
3245 
3246  if ( !m_rWW8Export.IsInTable() && rFormat.IsInline() )
3247  {
3248  //Test to see if this textbox contains only a single graphic/ole
3249  SwTextNode* pParTextNode = rAnch.GetContentAnchor()->nNode.GetNode().GetTextNode();
3250  if ( pParTextNode && !m_rWW8Export.m_pDoc->GetNodes()[ nStt ]->IsNoTextNode() )
3251  bDone = true;
3252  }
3253  if( !bDone )
3254  {
3255 
3256  m_rWW8Export.SaveData( nStt, nEnd );
3257 
3258  Point aOffset;
3260  {
3261  /* Munge flys in fly into absolutely positioned elements for word 6 */
3262  const SwTextNode* pParTextNode = rAnch.GetContentAnchor()->nNode.GetNode().GetTextNode();
3263  const SwRect aPageRect = pParTextNode->FindPageFrameRect();
3264 
3265  aOffset = rFrameFormat.FindLayoutRect().Pos();
3266  aOffset -= aPageRect.Pos();
3267 
3268  m_rWW8Export.m_pFlyOffset = &aOffset;
3269  m_rWW8Export.m_eNewAnchorType = RndStdIds::FLY_AT_PAGE;
3270  }
3271 
3272  m_rWW8Export.m_pParentFrame = &rFormat;
3273  if (
3274  m_rWW8Export.IsInTable() &&
3275  (RndStdIds::FLY_AT_PAGE != rAnch.GetAnchorId()) &&
3276  !m_rWW8Export.m_pDoc->GetNodes()[ nStt ]->IsNoTextNode()
3277  )
3278  {
3279  // note: set Flag bOutTable again,
3280  // because we deliver the normal content of the table cell, and no border
3281  // ( Flag was deleted above in aSaveData() )
3282  m_rWW8Export.m_bOutTable = true;
3283  const OUString& aName = rFrameFormat.GetName();
3287  }
3288  else
3290 
3292  }
3293  }
3294 }
3295 
3297 {
3298  if ( !rFormat.GetContentNode() )
3299  return;
3300 
3301  const SwContentNode &rNode = *rFormat.GetContentNode();
3302  Point aLayPos;
3303 
3304  // get the Layout Node-Position
3305  if (RndStdIds::FLY_AT_PAGE == rFormat.GetFrameFormat().GetAnchor().GetAnchorId())
3306  aLayPos = rNode.FindPageFrameRect().Pos();
3307  else
3308  aLayPos = rNode.FindLayoutRect().Pos();
3309 
3310  OutputFlyFrame_Impl( rFormat, aLayPos );
3311 }
3312 
3313 // write data of any redline
3315 {
3316  if ( !pRedline )
3317  return;
3318 
3319  if ( pRedline->Next() )
3320  Redline( pRedline->Next() );
3321 
3322  static const sal_uInt16 insSprmIds[ 3 ] =
3323  {
3324  // Ids for insert // for WW8
3326  };
3327  static const sal_uInt16 delSprmIds[ 3 ] =
3328  {
3329  // Ids for delete // for WW8
3331  };
3332 
3333  const sal_uInt16* pSprmIds = nullptr;
3334  switch( pRedline->GetType() )
3335  {
3336  case RedlineType::Insert:
3337  pSprmIds = insSprmIds;
3338  break;
3339 
3340  case RedlineType::Delete:
3341  pSprmIds = delSprmIds;
3342  break;
3343 
3344  case RedlineType::Format:
3346  m_rWW8Export.pO->push_back( 7 ); // len
3347  m_rWW8Export.pO->push_back( 1 );
3350  break;
3351  default:
3352  OSL_ENSURE(false, "Unhandled redline type for export");
3353  break;
3354  }
3355 
3356  if ( pSprmIds )
3357  {
3358  m_rWW8Export.InsUInt16( pSprmIds[0] );
3359  m_rWW8Export.pO->push_back( 1 );
3360 
3361  m_rWW8Export.InsUInt16( pSprmIds[1] );
3363 
3364  m_rWW8Export.InsUInt16( pSprmIds[2] );
3366  }
3367 }
3368 
3370 {
3371  switch ( rNode.GetNodeType() )
3372  {
3373  case SwNodeType::Text:
3374  OutputTextNode( *rNode.GetTextNode() );
3375  break;
3376  case SwNodeType::Grf:
3377  OutputGrfNode( *rNode.GetGrfNode() );
3378  break;
3379  case SwNodeType::Ole:
3380  OutputOLENode( *rNode.GetOLENode() );
3381  break;
3382  default:
3383  SAL_WARN("sw.ww8", "Unhandled node, type == " << static_cast<int>(rNode.GetNodeType()) );
3384  break;
3385  }
3386 }
3387 
3388 
3389 WW8Ruby::WW8Ruby(const SwTextNode& rNode, const SwFormatRuby& rRuby, const MSWordExportBase& rExport ):
3390  m_nJC(0),
3391  m_cDirective(0),
3392  m_nRubyHeight(0),
3393  m_nBaseHeight(0)
3394 {
3395  switch ( rRuby.GetAdjustment() )
3396  {
3397  case css::text::RubyAdjust_LEFT:
3398  m_nJC = 3;
3399  m_cDirective = 'l';
3400  break;
3401  case css::text::RubyAdjust_CENTER:
3402  //defaults to 0
3403  break;
3404  case css::text::RubyAdjust_RIGHT:
3405  m_nJC = 4;
3406  m_cDirective = 'r';
3407  break;
3408  case css::text::RubyAdjust_BLOCK:
3409  m_nJC = 1;
3410  m_cDirective = 'd';
3411  break;
3412  case css::text::RubyAdjust_INDENT_BLOCK:
3413  m_nJC = 2;
3414  m_cDirective = 'd';
3415  break;
3416  default:
3417  OSL_ENSURE( false,"Unhandled Ruby justification code" );
3418  break;
3419  }
3420 
3421  if ( rRuby.GetPosition() == css::text::RubyPosition::INTER_CHARACTER )
3422  {
3423  m_nJC = 5;
3424  m_cDirective = 0;
3425  }
3426 
3427  /*
3428  MS needs to know the name and size of the font used in the ruby item,
3429  but we could have written it in a mixture of asian and western
3430  scripts, and each of these can be a different font and size than the
3431  other, so we make a guess based upon the first character of the text,
3432  defaulting to asian.
3433  */
3434  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
3435  sal_uInt16 nRubyScript = g_pBreakIt->GetBreakIter()->getScriptType(rRuby.GetText(), 0);
3436 
3437  const SwTextRuby* pRubyText = rRuby.GetTextRuby();
3438  const SwCharFormat* pFormat = pRubyText ? pRubyText->GetCharFormat() : nullptr;
3439 
3440  if (pFormat)
3441  {
3442  const auto& rFont
3443  = ItemGet<SvxFontItem>(*pFormat, GetWhichOfScript(RES_CHRATR_FONT, nRubyScript));
3444  m_sFontFamily = rFont.GetFamilyName();
3445 
3446  const auto& rHeight = ItemGet<SvxFontHeightItem>(
3447  *pFormat, GetWhichOfScript(RES_CHRATR_FONTSIZE, nRubyScript));
3448  m_nRubyHeight = rHeight.GetHeight();
3449  }
3450  else
3451  {
3452  /*Get defaults if no formatting on ruby text*/
3453 
3454  const SfxItemPool* pPool = rNode.GetSwAttrSet().GetPool();
3455  pPool = pPool ? pPool : &rExport.m_pDoc->GetAttrPool();
3456 
3457 
3458  const auto& rFont
3459  = DefaultItemGet<SvxFontItem>(*pPool, GetWhichOfScript(RES_CHRATR_FONT, nRubyScript));
3460  m_sFontFamily = rFont.GetFamilyName();
3461 
3462  const auto& rHeight = DefaultItemGet<SvxFontHeightItem>(
3463  *pPool, GetWhichOfScript(RES_CHRATR_FONTSIZE, nRubyScript));
3464  m_nRubyHeight = rHeight.GetHeight();
3465  }
3466 
3467  if (pRubyText)
3468  nRubyScript
3469  = g_pBreakIt->GetBreakIter()->getScriptType(rNode.GetText(), pRubyText->GetStart());
3470  else
3471  nRubyScript = i18n::ScriptType::ASIAN;
3472 
3473  const OUString &rText = rNode.GetText();
3474  sal_uInt16 nScript = i18n::ScriptType::LATIN;
3475 
3476  if (!rText.isEmpty())
3477  nScript = g_pBreakIt->GetBreakIter()->getScriptType(rText, 0);
3478 
3479  sal_uInt16 nWhich = GetWhichOfScript(RES_CHRATR_FONTSIZE, nScript);
3480  auto& rHeightItem = static_cast<const SvxFontHeightItem&>(rExport.GetItem(nWhich));
3481  m_nBaseHeight = rHeightItem.GetHeight();
3482 }
3483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long GetLeft() const
bool GetValue() const
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:960
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
virtual void WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner=ww8::WW8TableNodeInfoInner::Pointer_t())=0
SvxBreak
OUString GetSnippet(const OUString &rStr, sal_Int32 nCurrentPos, sal_Int32 nLen) const
Definition: wrtw8nds.cxx:1667
TOXTypes
Definition: toxe.hxx:39
virtual AttributeOutputBase & AttrOutput() const =0
Access to the attribute output class.
virtual void OutputOLENode(const SwOLENode &)=0
Output SwOLENode.
bool Insert(const SvxTabStop &rTab)
sal_uLong GetIndex() const
Definition: node.hxx:282
const OUString & GetBaseURL() const
Definition: shellio.hxx:439
virtual void AppendSmartTags(SwTextNode &)
Definition: wrtww8.hxx:704
virtual const OUString & GetName() const =0
std::unique_ptr< ww::bytes > pO
Buffer.
Definition: wrtww8.hxx:980
void GetCurrentItems(ww::bytes &rItems) const
Definition: wrtw8nds.cxx:814
bool m_bLinkedTextboxesHelperInitialized
Definition: wrtww8.hxx:513
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
sal_uInt16 AddRedlineAuthor(std::size_t nId)
Definition: wrtww8.cxx:1682
bool IsSaveRelFSys() const
virtual void FormatDrop(const SwTextNode &rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner)=0
const SwFormatLayoutSplit & GetLayoutSplit(bool=true) const
Definition: fmtlsplt.hxx:46
Marks a position in the document model.
Definition: pam.hxx:35
void OutSwString(const OUString &, sal_Int32 nStt, sal_Int32 nLen)
Definition: wrtww8.cxx:1860
bool GetWholeWord() const
Definition: paratr.hxx:92
bool IsSectionNode() const
Definition: node.hxx:644
#define RES_CHRATR_CJK_LANGUAGE
Definition: hintids.hxx:92
std::unique_ptr< WW8Fib > pFib
File Information Block.
Definition: wrtww8.hxx:984
virtual void SectionBreaks(const SwNode &rNode)=0
Called in order to output section breaks.
ww8::Frames GetFramesInNode(const ww8::Frames &rFrames, const SwNode &rNode)
Get the Frames anchored to a given node.
const SfxPoolItem & GetItem(sal_uInt16 nWhich) const
Definition: wrtww8.cxx:803
static const SwPageDesc * GetPageDescOfNode(const SwNode &rNd)
Given a SwNode return the pagedesc in use at that location.
Definition: pagedesc.cxx:311
OUString & GetRefName()
Definition: fmtrfmrk.hxx:66
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SvxAdjust GetAdjust() const
sal_uInt8 SVBT16[2]
virtual void EndParagraphProperties(const SfxItemSet &rParagraphMarkerProperties, const SwRedlineData *pRedlineData, const SwRedlineData *pRedlineParagraphMarkerDeleted, const SwRedlineData *pRedlineParagraphMarkerInserted)=0
Called after we end outputting the attributes.
#define ODF_OLE_PARAM
sal_Char GetDirective()
#define RES_CHRATR_FONTSIZE
Definition: hintids.hxx:76
SwOLENode * GetOLENode()
Inline methods from Node.hxx.
Definition: ndole.hxx:161
void WriteStringAsPara(const OUString &rText)
Definition: wrtww8.cxx:1804
SwTableBox * GetTableBox() const
If node is in a table return the respective table box.
Definition: node.cxx:745
const sal_uInt16 sprmPWr
Definition: sprmids.hxx:381
#define RES_CHRATR_LANGUAGE
Definition: hintids.hxx:78
#define RES_TXTATR_CJK_RUBY
Definition: hintids.hxx:143
RndStdIds m_eNewAnchorType
Definition: wrtww8.hxx:520
bool m_bAddFootnoteTab
Definition: wrtww8.hxx:570
const OUString & GetText() const
Definition: ndtxt.hxx:211
OUString const & GetPrimaryKey() const
Definition: tox.hxx:604
#define RES_PARATR_GRABBAG
Definition: hintids.hxx:179
#define ODF_PAGEREF
sal_uInt16 GetId(const SwTextFormatColl &rColl) const
Return the numeric id of the style.
Definition: wrtw8sty.cxx:134
#define RES_TXTATR_METAFIELD
Definition: hintids.hxx:139
const SwFormatDrop & mrSwFormatDrop
Definition: wrtww8.hxx:1507
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:219
std::string GetValue
const SwRedlineData * Next() const
Definition: redline.hxx:130
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: node.cxx:1156
short GetTextFirstLineOfst() const
const sal_uInt16 sprmCDttmRMarkDel
Definition: sprmids.hxx:328
std::multimap< sal_Int32, OUString > m_aBookmarksOfParagraphEnd
const SwNumFormat * GetNumFormat(sal_uInt16 i) const
Definition: number.cxx:93
OUString GetURLPath(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
SwNodeIndex nNode
Definition: pam.hxx:37
virtual bool AnalyzeURL(const OUString &rURL, const OUString &rTarget, OUString *pLinkURL, OUString *pMark) override
Definition: wrtw8nds.cxx:955
std::size_t GetAuthor() const
Definition: redline.hxx:127
const sal_uInt16 sprmPDxaFromText
Definition: sprmids.hxx:393
SvxBreak GetBreak() const
virtual void Redline(const SwRedlineData *pRedline) override
Output redlining.
Definition: wrtw8nds.cxx:3314
const SwRedlineData * GetParagraphLevelRedline()
Definition: wrtw8nds.cxx:1422
std::vector< sal_uInt8 > bytes
Definition: types.hxx:29
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:284
sal_uInt8 GetLines() const
Definition: paratr.hxx:86
sal_uIntPtr sal_uLong
virtual void EndRuby(const SwTextNode &rNode, sal_Int32 nPos)=0
Output ruby end.
static void WriteString8(SvStream &rStrm, const OUString &rStr, bool bAddZero, rtl_TextEncoding eCodeSet)
Definition: wrtww8.cxx:1791
#define RES_FRAMEDIR
Definition: hintids.hxx:225
static SW_DLLPUBLIC MarkType GetType(const ::sw::mark::IMark &rMark)
Returns the MarkType used to create the mark.
Definition: docbm.cxx:483
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: atrfrm.cxx:2633
const SwPosition * GetMark() const
Definition: pam.hxx:209
const SwAttrSet * m_pStyAttr
Definition: wrtww8.hxx:534
const SvxFrameDirectionItem & GetFrameDir(bool=true) const
Definition: frmatr.hxx:94
const SwPageDesc * FindPageDesc(size_t *pPgDescNdIdx=nullptr) const
Search PageDesc with which this node is formatted.
Definition: node.cxx:466
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
Definition: langhelper.cxx:402
rtl_TextEncoding meChrSet
Definition: wrtww8.hxx:1497
SwFrameFormat & GetFirstMaster()
Definition: pagedesc.hxx:218
bool MiserableFormFieldExportHack(const SwFrameFormat &rFrameFormat)
Definition: wrtw8esh.cxx:364
Provides access to the marks of a document.
bool m_bOutPageDescs
PageDescs (section properties) are being written.
Definition: wrtww8.hxx:551
#define ODF_FORMCHECKBOX
bool mbCharIsRTL
Definition: wrtww8.hxx:1499
const sal_uInt16 sprmCHps
Definition: sprmids.hxx:302
virtual void StartRuby(const SwTextNode &rNode, sal_Int32 nPos, const SwFormatRuby &rRuby)=0
Output ruby start.
virtual void OutputLinkedOLE(const OUString &)=0
sal_uInt16 FirstWhich()
#define ODF_CODE_PARAM
std::stack< sal_Int32 > m_aCurrentCharPropStarts
To remember the position in a run.
Definition: wrtww8.hxx:469
#define RES_CHRATR_FONT
Definition: hintids.hxx:75
bool NeedSectionBreak(const SwNode &rNd) const
Definition: wrtw8nds.cxx:2080
bool HasDummyChar() const
Definition: txatbase.hxx:101
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
void SetTextLeft(const long nL, const sal_uInt16 nProp=100)
SwNode & GetNode() const
Definition: ndindex.hxx:118
const OUString & GetName() const
Definition: numrule.hxx:222
bool GetNewAbsURL(OUString const &rTheRelURIRef, INetURLObject *pTheAbsURIRef) const
Point * m_pFlyOffset
Definition: wrtww8.hxx:519
const std::shared_ptr< SfxItemSet > & GetStyleHandle() const
Definition: fmtautofmt.hxx:49
SvxFrameDirection
static OUString GetRelURL(OUString const &rTheBaseURIRef, OUString const &rTheAbsURIRef, EncodeMechanism eEncodeMechanism=EncodeMechanism::WasEncoded, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8, FSysStyle eStyle=FSysStyle::Detect)
SwSectionFormat * GetFormat()
Definition: section.hxx:337
SvxFrameDirection GetTextDirection(const SwPosition &rPos, const Point *pPt=nullptr) const
Definition: doclay.cxx:1614
sal_uInt16 m_nStyleBeforeFly
style number of the node
Definition: wrtww8.hxx:480
void Pos(const Point &rNew)
Definition: swrect.hxx:167
bool AreListLevelIndentsApplicable() const
Determines, if the list level indent attributes can be applied to the paragraph.
Definition: ndtxt.cxx:4411
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1552
virtual void StartRunProperties()=0
Called before we start outputting the attributes.
WW8_CP Fc2Cp(sal_uLong nFc) const
Definition: wrtww8.hxx:1094
const SwTOXType * GetTOXType() const
Definition: tox.hxx:542
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
#define RES_TXTATR_CHARFMT
Definition: hintids.hxx:142
sal_uInt16 Which() const
Definition: txatbase.hxx:110
void Set_UInt32(sal_uInt8 *&p, sal_uInt32 n)
Definition: ww8struc.hxx:53
virtual sal_Int32 getAnnotationMarksCount() const =0
void OutputItemSet(const SfxItemSet &rSet, bool bPapFormat, bool bChpFormat, sal_uInt16 nScript, bool bExportParentItemSet)
Use OutputItem() on an item set according to the parameters.
Definition: ww8atr.cxx:259
void AppendFlyInFlys(const ww8::Frame &rFrameFormat, const Point &rNdTopLeft)
Definition: wrtw8esh.cxx:981
bool operator()(const ww8::Frame &rOne, const ww8::Frame &rTwo) const
Definition: wrtw8nds.cxx:177
#define RES_TXTATR_END
Definition: hintids.hxx:158
SVL_DLLPUBLIC OUString simpleNormalizedMakeRelative(OUString const &baseUriReference, OUString const &uriReference)
virtual const SfxPoolItem * HasTextItem(sal_uInt16 nWhich) const override
Definition: wrtw8nds.cxx:773
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:50
OUString FieldString(ww::eField eIndex)
Definition: ww8atr.cxx:2582
virtual ExportFormat GetExportFormat() const =0
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4096
std::shared_ptr< SvxBrushItem > TrueFrameBgBrush(const SwFrameFormat &rFlyFormat) const
Definition: wrtw8nds.cxx:1618
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:201
sal_uInt32 m_nBaseHeight
const SwRedlineData * GetParagraphMarkerRedline(const SwTextNode &rNode, RedlineType aRedlineType)
Definition: ww8atr.cxx:5492
size_type size() const
Definition: swtable.hxx:74
sal_uInt16 NextWhich()
IMarkVector m_rSortedAnnotationMarksEnd
Definition: wrtww8.hxx:585
const sal_uInt16 sprmPDyaLine
Definition: sprmids.hxx:371
void GetPoolItems(const SfxItemSet &rSet, ww8::PoolItems &rItems, bool bExportParentItemSet)
Get the SfxPoolItems of a SfxItemSet.
virtual void SetAnchorIsLinkedToNode(bool)
If the node has an anchor linked.
ww8::FrameIter maFlyIter
Definition: wrtww8.hxx:1510
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:174
OUString PathToFileName() const
size_type size() const
Definition: docary.hxx:368
OUString BookmarkToWord(const OUString &rBookmark)
Definition: wrtw8nds.cxx:1145
const SwSection & GetSection() const
Definition: node.hxx:541
sal_Int32 WhereNext() const
Definition: wrtww8.hxx:1540
sal_uInt16 GetScript() const
Definition: wrtww8.hxx:1541
void GenerateBookmarksForSequenceField(const SwTextNode &rNode, SwWW8AttrIter &rAttrIter)
MSO uses bookmarks to reference sequence fields, so we need to generate these additional bookmarks du...
Definition: ww8atr.cxx:1990
#define ODF_HYPERLINK
const sal_uInt16 sprmCDttmRMark
Definition: sprmids.hxx:275
void WriteText()
Iterate through the nodes and call the appropriate OutputNode() on them.
Definition: wrtww8.cxx:2710
sal_uInt16 sal_Unicode
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
const OUString & GetValue() const
Definition: fmtinfmt.hxx:75
const SwTextRuby * GetTextRuby() const
Definition: fmtruby.hxx:59
RedlineType GetType() const
Definition: redline.hxx:125
virtual void PageBreakBefore(bool bBreak)=0
Page break As a paragraph property - the paragraph should be on the next page.
virtual void AppendBookmarks(const SwTextNode &rNd, sal_Int32 nCurrentPos, sal_Int32 nLen)=0
virtual void OutputField(const SwField *pField, ww::eField eFieldType, const OUString &rFieldCmd, FieldFlags nMode=FieldFlags::All) override
Write the field.
Definition: ww8atr.cxx:1737
SwWW8AttrIter(const SwWW8AttrIter &)=delete
SwNodeType GetNodeType() const
Definition: node.hxx:144
MSWordExportBase & m_rExport
Definition: wrtww8.hxx:1431
std::map< OUString, LinkedTextboxInfo > m_aLinkedTextboxesHelper
Definition: wrtww8.hxx:512
SwIndex nContent
Definition: pam.hxx:38
bool empty() const
Definition: docary.hxx:367
virtual ::sw::mark::IFieldmark * getFieldmarkFor(const SwPosition &pos) const =0
void OutputFormat(const SwFormat &rFormat, bool bPapFormat, bool bChpFormat, bool bFlyFormat=false)
Output attributes.
Definition: ww8atr.cxx:756
virtual bool StartURL(const OUString &rUrl, const OUString &rTarget) override
Output URL start.
Definition: wrtw8nds.cxx:986
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const override
#define RES_PARATR_TABSTOP
Definition: hintids.hxx:166
const OUString & GetName() const
Definition: format.hxx:111
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
void StartTOX(const SwSection &rSect)
Definition: ww8atr.cxx:2159
sal_uLong GetIndex() const
Definition: ndindex.hxx:151
const sal_uInt16 sprmCFRMarkDel
Definition: sprmids.hxx:270
eField
Definition: fields.hxx:26
virtual void StartRun(const SwRedlineData *pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun=false)=0
Start of the text run.
sal_Int32 GetStart() const
Definition: txatbase.hxx:82
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
const SvxBrushItem * GetCurrentPageBgBrush() const
Definition: wrtw8nds.cxx:1599
MSWordAttrIter * m_pChpIter
Definition: wrtww8.hxx:498
bool m_bInWriteEscher
Definition: wrtww8.hxx:556
virtual void SetStateOfFlyFrame(FlyProcessingState)
Set the state of the Fly at current position.
virtual void StartParagraphProperties()=0
Called before we start outputting the attributes.
#define RES_UL_SPACE
Definition: hintids.hxx:197
virtual bool IsFlyProcessingPostponed()
Is processing of fly postponed ?
const SwTable & GetTable() const
Definition: node.hxx:497
virtual void ResetFlyProcessingFlag()
Reset the flag for FlyProcessing.
virtual parameter_map_t * GetParameters()=0
sal_uInt16 GetDistance() const
Definition: paratr.hxx:95
const SvxFormatKeepItem & GetKeep(bool=true) const
Definition: frmatr.hxx:86
bool HasRefToObject(sal_uInt16 nTyp, const OUString *pName, sal_uInt16 nSeqNo)
Find the reference.
Definition: ww8atr.cxx:892
const Graphic * GetGraphic(OUString const &referer=OUString()) const
#define RES_PARATR_NUMRULE
Definition: hintids.hxx:170
void WriteChar(sal_Unicode c) override
Definition: wrtww8.cxx:1897
INetProtocol
ww8::Frames maFlyFrames
Definition: wrtww8.hxx:1509
#define RES_CHRATR_CASEMAP
Definition: hintids.hxx:69
const sal_uInt16 sprmCIbstRMarkDel
Definition: sprmids.hxx:327
static void UpdateTocSectionNodeProperties(const SwSectionNode &rSectionNode)
Definition: wrtw8nds.cxx:3111
ww8::WW8TableInfo::Pointer_t m_pTableInfo
Definition: wrtww8.hxx:476
void OutputItem(const SfxPoolItem &rHt)
Call the right virtual function according to the type of the item.
Definition: ww8atr.cxx:5156
css::uno::Sequence< css::beans::PropertyValue > InitPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
SwAttrPool * GetPool() const
Definition: swatrset.hxx:190
rtl_TextEncoding GetCharSet() const
Definition: wrtww8.hxx:1543
const SwFrameFormat & GetFrameFormat() const
Get the writer SwFrameFormat that this object describes.
const SwRedlineData & GetRedlineData(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1757
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:716
const sal_uInt16 sprmPPc
Definition: sprmids.hxx:380
const T & item_cast(const SfxPoolItem &rItem)
Provide a dynamic_cast style cast for SfxPoolItems.
void GetSortedAnnotationMarks(const SwWW8AttrIter &rAttrs, sal_Int32 nCurrentPos, sal_Int32 nLen)
Definition: wrtw8nds.cxx:2013
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:164
const OUString & GetText() const
Definition: fmtruby.hxx:61
#define RES_BACKGROUND
Definition: hintids.hxx:210
static void WriteString16(SvStream &rStrm, const OUString &rStr, bool bAddZero)
Definition: wrtww8.cxx:1768
void IterToCurrent()
Definition: wrtw8nds.cxx:183
virtual const_iterator_t getAllMarksBegin() const =0
returns a STL-like random access iterator to the begin of the sequence of marks.
const Color & GetColor() const
virtual sal_uLong ReplaceCr(sal_uInt8 nChar)=0
const OUString & GetAlternativeText() const
Definition: tox.hxx:533
bool IsContentNode() const
Definition: node.hxx:628
const sal_uInt16 sprmCIstd
Definition: sprmids.hxx:287
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:443
void NextPos()
Definition: wrtww8.hxx:1529
virtual bool AnalyzeURL(const OUString &rUrl, const OUString &rTarget, OUString *pLinkURL, OUString *pMark)
Definition: wrtw8nds.cxx:902
std::unique_ptr< WW8_WrPlcPn > m_pPapPlc
Definition: wrtww8.hxx:496
sal_uInt16 GetPosition() const
Definition: fmtruby.hxx:70
WW8Export & m_rWW8Export
Reference to the export, where to get the data from.
void OutputSectionNode(const SwSectionNode &)
Output SwSectionNode.
Definition: wrtw8nds.cxx:3058
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
Style of a layout element.
Definition: frmfmt.hxx:57
size_t Count() const
Definition: ndhints.hxx:142
#define SAL_MAX_INT32
virtual void RunText(const OUString &rText, rtl_TextEncoding eCharSet=RTL_TEXTENCODING_UTF8)=0
Output text (inside a run).
static bool isRightToLeft(LanguageType nLang)
sal_Int32 GetNextPos(SwWW8AttrIter const *pAttrIter, const SwTextNode &rNode, sal_Int32 nCurrentPos)
Get the next position in the text node to output.
Definition: wrtw8nds.cxx:1829
const sal_uInt8 ND_HAS_PREV_LAYNODE
Definition: ndtyp.hxx:63
void SplitRun(sal_Int32 nSplitEndPos)
Definition: wrtw8nds.cxx:1169
virtual ~MSWordAttrIter()
Definition: wrtw8nds.cxx:169
virtual void FormatDrop(const SwTextNode &rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner) override
Definition: wrtw8nds.cxx:1765
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void SetCurItemSet(const SfxItemSet *pS)
Setter for pISet.
Definition: wrtww8.hxx:723
std::map< sal_uInt16, const SfxPoolItem *, sw::util::ItemSort > PoolItems
STL container of SfxPoolItems (Attributes)
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
std::vector< Frame >::iterator FrameIter
STL iterator for Frames.
std::unique_ptr< WW8_WrPlcSepx > pSepx
Sections/headers/footers.
Definition: wrtww8.hxx:988
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
sal_Int32 GetAbsLSpace() const
WW8Ruby(const SwTextNode &rNode, const SwFormatRuby &rRuby, const MSWordExportBase &rExport)
Definition: wrtw8nds.cxx:3389
void NearestAnnotationMark(sal_Int32 &rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly)
Find the nearest annotation mark from the current position.
Definition: wrtw8nds.cxx:1984
void UpdatePosition(SwWW8AttrIter *pAttrIter, sal_Int32 nCurrentPos)
Update the information for GetNextPos().
Definition: wrtw8nds.cxx:1846
const SwPosition * GetPoint() const
Definition: pam.hxx:207
OUString GetURLNoMark(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
sal_uInt16 mnScript
Definition: wrtww8.hxx:1498
FlyProcessingState OutFlys(sal_Int32 nSwPos)
Definition: wrtw8nds.cxx:585
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
const SwPageDesc & GetPageDesc(const size_t i) const
Definition: doc.hxx:876
const SwTOXBase * GetTOXBase() const
Definition: section.cxx:620
const sal_uInt16 sprmCIbstRMark
Definition: sprmids.hxx:274
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
bool IsParaRTL() const
Definition: wrtww8.hxx:1542
sal_Int32 GetJC()
const SwModify * m_pOutFormatNode
Definition: wrtww8.hxx:535
virtual void OutputTextNode(SwTextNode &)
Output SwTextNode.
Definition: wrtw8nds.cxx:2106
sw::util::CharRuns maCharRuns
Definition: wrtww8.hxx:1494
void OutputContentNode(SwContentNode &)
Call the right (virtual) function according to the type of the item.
Definition: wrtw8nds.cxx:3369
bool HasContent() const
Definition: txatbase.hxx:106
virtual void ExportGrfBullet(const SwTextNode &rNd)=0
int i
void OutputSectionBreaks(const SfxItemSet *pSet, const SwNode &rNd, bool isCellOpen=false, bool isTextNodeEmpty=false)
Start new section.
Definition: ww8atr.cxx:410
SwContentNode * GetContentNode()
Definition: node.hxx:615
sal_uInt8 HasPrevNextLayNode() const
Definition: node.cxx:841
vector_type::size_type size_type
Definition: docary.hxx:330
FlyAnchors.
Definition: fmtanchr.hxx:34
sal_uInt16 GetLevel() const
Definition: tox.hxx:598
static void WriteShort(SvStream &rStrm, sal_Int16 nVal)
Definition: wrtww8.hxx:951
const ww8::Frame * m_pParentFrame
Definition: wrtww8.hxx:516
virtual WW8Export & GetExport() override
Return the right export class.
MSWordAttrIter *const pOld
Definition: wrtww8.hxx:1427
static sal_Int32 lcl_getMinPos(sal_Int32 pos1, sal_Int32 pos2)
Definition: wrtw8nds.cxx:237
std::size_t WriteBytes(const void *pData, std::size_t nSize)
sal_uInt32 GetRubyHeight()
virtual void StartParagraph(ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo)=0
Start of the paragraph.
Marks a character position inside a document model node.
Definition: index.hxx:37
const SfxItemSet * GetItemSet(const SfxPoolItem &rAttr)
Returns the item set associated with a character/inet/auto style.
Definition: atrstck.cxx:133
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:52
const SwRedlineData * GetRunLevelRedline(sal_Int32 nPos)
Definition: wrtw8nds.cxx:1447
#define RES_CHRATR_BEGIN
Definition: hintids.hxx:68
sal_uInt16 GetWhichOfScript(sal_uInt16 nWhich, sal_uInt16 nScript)
Definition: hints.cxx:195
const DateTime & GetTimeStamp() const
Definition: redline.hxx:129
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2813
SvxFrameDirection GetDefaultFrameDirection() const
Definition: wrtw8nds.cxx:1527
const std::map< OUString, css::uno::Any > & GetGrabBag() const
static OUString GetScheme(INetProtocol eTheScheme)
virtual void OutputField(const SwField *pField, ww::eField eFieldType, const OUString &rFieldCmd, FieldFlags nMode=FieldFlags::All)=0
Write the field.
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:366
virtual const_iterator_t getAnnotationMarksBegin() const =0
bool KnowsPageDesc() const
Definition: atrfrm.cxx:616
void OutputFlyFrame(const ww8::Frame &rFormat)
Output frames.
Definition: wrtw8nds.cxx:3296
virtual void EndRuby(const SwTextNode &rNode, sal_Int32 nPos) override
Output ruby end.
Definition: wrtw8nds.cxx:859
size
virtual void WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner=ww8::WW8TableNodeInfoInner::Pointer_t()) override
Definition: wrtww8.cxx:1887
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:396
#define RES_TXTATR_TOXMARK
Definition: hintids.hxx:137
Marks a node in the document model.
Definition: ndindex.hxx:31
#define RES_LINENUMBER
Definition: hintids.hxx:221
SwWW8Writer & GetWriter() const
Definition: wrtww8.hxx:1169
bool IsEndNode() const
Definition: node.hxx:632
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:693
void StartCommentOutput(const OUString &rName)
Definition: ww8atr.cxx:1875
static void CorrectTabStopInSet(SfxItemSet &rSet, sal_Int32 nAbsLeft)
Definition: ww8atr.cxx:668
const sal_uInt16 sprmCPropRMark90
Definition: sprmids.hxx:316
const SvxFormatBreakItem & GetBreak(bool=true) const
Definition: frmatr.hxx:90
bool HasSwAttrSet() const
Definition: node.hxx:444
void InsUInt16(sal_uInt16 n)
Definition: wrtww8.hxx:1141
sal_Char m_cDirective
sal_uInt8 GetChars() const
Definition: paratr.hxx:89
DocumentType const eType
virtual void OutputGrfNode(const SwGrfNode &)=0
Output SwGrfNode.
virtual void TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo)=0
const sal_Unicode cMarkSeparator
Definition: swtypes.hxx:137
const SwRangeRedline * pCurRedline
Definition: wrtww8.hxx:1501
SvxNumPositionAndSpaceMode GetPositionAndSpaceMode() const
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:356
void InsUInt32(sal_uInt32 n)
Definition: wrtww8.hxx:1143
#define RES_TXTATR_INETFMT
Definition: hintids.hxx:141
void EndTOX(const SwSection &rSect, bool bCareEnd=true)
Definition: ww8atr.cxx:2479
SwTableLines & GetTabLines()
Definition: swtable.hxx:198
OUString GetName() const
IMarkVector m_rSortedAnnotationMarksStart
Definition: wrtww8.hxx:584
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:110
sal_Int16 GetWordFirstLineOffset(const SwNumFormat &rFormat)
Definition: wrtw8num.cxx:148
const SwPosition * Start() const
Definition: pam.hxx:212
sal_uInt32 GetBaseHeight()
void GetSortedBookmarks(const SwTextNode &rNd, sal_Int32 nCurrentPos, sal_Int32 nLen)
Definition: wrtw8nds.cxx:2047
OUString const & GetFontFamily()
#define RES_LR_SPACE
Definition: hintids.hxx:196
const SwPageDesc * GetFollow() const
Definition: pagedesc.hxx:245
virtual void EndRunProperties(const SwRedlineData *pRedlineData)=0
Called after we end outputting the attributes.
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
static ww::eField lcl_getFieldId(const IFieldmark *pFieldmark)
Definition: wrtw8nds.cxx:142
CharRuns GetPseudoCharRuns(const SwTextNode &rTextNd)
Collect the ranges of Text which share.
long GetIndentAt() const
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:458
bool operator()(const IMark *pOneB, const IMark *pTwoB) const
Definition: wrtw8nds.cxx:1943
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
void fillSoftPageBreakList(SwSoftPageBreakList &rBreak) const
const SwTextNode & rNd
Definition: wrtww8.hxx:1492
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:83
virtual void RTLAndCJKState(bool bIsRTL, sal_uInt16 nScript)=0
Export the state of RTL/CJK.
#define ODF_UNHANDLED
const css::lang::Locale & GetLocale(const LanguageType aLang)
Definition: breakit.hxx:67
SwFrameFormat & GetMaster()
Definition: pagedesc.hxx:216
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
void OutSwFormatRefMark(const SwFormatRefMark &rAttr)
Definition: wrtw8nds.cxx:1162
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
sal_Int32 GetDropLen(sal_Int32 nWishLen) const
nWishLen = 0 indicates that we want a whole word
Definition: txtdrop.cxx:124
void SetCaseMap(const SvxCaseMap eNew)
virtual void WriteBookmarkInActParagraph(const OUString &rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos) override
Insert a bookmark inside the currently processed paragraph.
Definition: wrtw8nds.cxx:980
sal_uInt32 m_nRubyHeight
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:173
const sal_uInt16 sprmCFFldVanish
Definition: sprmids.hxx:272
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:367
IMarkVector m_rSortedBookmarksEnd
Definition: wrtww8.hxx:583
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:439
#define RES_TXTATR_AUTOFMT
Definition: hintids.hxx:140
OUString BookmarkToWriter(const OUString &rBookmark)
Definition: wrtw8nds.cxx:1156
#define ODF_TOC
const SwPageDesc * m_pCurrentPageDesc
Definition: wrtww8.hxx:493
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:67
SfxItemState
OUString GetExpandText(SwRootFrame const *pLayout, const sal_Int32 nIdx=0, const sal_Int32 nLen=-1, const bool bWithNum=false, const bool bAddSpaceAfterListLabelStr=false, const bool bWithSpacesForLevel=false, const ExpandMode eAdditionalMode=ExpandMode::ExpandFootnote) const
add 4th optional parameter indicating, when that a spa...
Definition: ndtxt.cxx:3383
void SetTextFirstLineOfst(const short nF, const sal_uInt16 nProp=100)
virtual void StartRuby(const SwTextNode &rNode, sal_Int32 nPos, const SwFormatRuby &rRuby) override
Output ruby start.
Definition: wrtw8nds.cxx:825
bool HasFlysAt(sal_Int32 nSwPos) const
Definition: wrtw8nds.cxx:570
virtual const SfxPoolItem & GetItem(sal_uInt16 nWhich) const override
Definition: wrtw8nds.cxx:819
static OUString & TruncateBookmark(OUString &rRet)
Definition: wrtw8nds.cxx:866
bool GetDropSize(int &rFontHeight, int &rDropHeight, int &rDropDescent) const
Passes back info needed on the dropcap dimensions.
Definition: txtdrop.cxx:230
virtual sal_Int32 getAllMarksCount() const =0
returns the number of marks.
SvStream & Strm() const
Definition: wrtww8.hxx:1170
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
OUString const & GetSecondaryKey() const
Definition: tox.hxx:610
virtual bool AllowPostponedTextInTable() const
Text in tables can be postponed except for .doc.
Definition: wrtww8.hxx:684
std::set< sal_Int32 > SwSoftPageBreakList
Definition: wrtww8.hxx:137
FlyProcessingState
enum to state the present state of the fly
Definition: wrtww8.hxx:169
#define RES_CHRATR_CTL_LANGUAGE
Definition: hintids.hxx:97
unsigned char sal_uInt8
const sal_uInt16 sprmCFRMarkIns
Definition: sprmids.hxx:271
const OUString & GetTargetFrame() const
Definition: fmtinfmt.hxx:89
Make exporting a Writer Frame easy.
bool IsDropCap(int nSwPos)
Definition: wrtw8nds.cxx:744
bool IsNumbered(SwRootFrame const *pLayout=nullptr) const
Returns is this text node is numbered.
Definition: ndtxt.cxx:2888
const SwContentNode * GetContentNode() const
Get the node this frame is anchored into.
bool IncludeEndOfParaCRInRedlineProperties(sal_Int32 nPos) const
Definition: wrtw8nds.cxx:1366
bool IsWatermarkFrame()
Definition: wrtw8nds.cxx:531
TOXTypes GetType() const
Definition: tox.hxx:695
sal_uInt32 DateTime2DTTM(const DateTime &rDT)
Convert from DTTM to Writer's DateTime.
virtual void AppendAnnotationMarks(const SwWW8AttrIter &rAttrs, sal_Int32 nCurrentPos, sal_Int32 nLen)=0
#define SAL_INFO(area, stream)
SvStream & WriteUChar(unsigned char nChar)
sal_Int32 GetIndex() const
Definition: index.hxx:95
SvStream * pDataStrm
Streams for WW97 Export.
Definition: wrtww8.hxx:982
bool IsCountedInList() const
Definition: ndtxt.cxx:4239
INetProtocol GetProtocol() const
#define ODF_FORMTEXT
LanguageType GetAppLanguage()
Definition: init.cxx:765
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:208
SwNodes & GetNodes()
Definition: doc.hxx:402
const sal_uInt8 PageBreak
std::pair< OUString, sal_uLong > aBookmarkPair
Definition: wrtww8.hxx:413
sw::util::CharRuns::const_iterator maCharRunIter
Definition: wrtww8.hxx:1495
const SwPosition * End() const
Definition: pam.hxx:217
OUString CalcCaseMap(const OUString &rTxt) const
#define RES_KEEP
Definition: hintids.hxx:215
std::multimap< sal_Int32, OUString > m_aBookmarksOfParagraphStart
Bookmarks of the current paragraph.
virtual void SaveData(sal_uLong nStt, sal_uLong nEnd) override
Remember some of the members so that we can recurse in WriteText().
Definition: wrtww8.cxx:1974
sal_uInt8 m_nTextTyp
Definition: wrtww8.hxx:545
ww8::Frames m_aFrames
Definition: wrtww8.hxx:492
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1739
const sal_Int32 * End() const
Definition: txatbase.hxx:148
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:386
bool m_bOutFlyFrameAttrs
Definition: wrtww8.hxx:550
bool NearestBookmark(sal_Int32 &rNearest, const sal_Int32 nCurrentPos, bool bNextPositionOnly)
Find the nearest bookmark from the current position.
Definition: wrtw8nds.cxx:1952
virtual void FieldVanish(const OUString &rText, ww::eField eType)=0
virtual bool EndURL(bool isAtEndOfParagraph)=0
Output URL end.
sal_uInt64 Tell() const
#define RES_PARATR_ADJUST
Definition: hintids.hxx:162
std::shared_ptr< WW8TableNodeInfoInner > Pointer_t
bool m_bInWriteTOX
Definition: wrtww8.hxx:558
virtual void AppendSection(const SwPageDesc *pPageDesc, const SwSectionFormat *pFormat, sal_uLong nLnNum) override
Definition: wrtw8nds.cxx:3198
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
bool IsPlausableSingleWordSection(const SwFrameFormat &rTitleFormat, const SwFrameFormat &rFollowFormat)
See if two page formats can be expressed as a single word section.
virtual void ParagraphStyle(sal_uInt16 nStyle)=0
Output style.
bool GetBookmarks(const SwTextNode &rNd, sal_Int32 nStt, sal_Int32 nEnd, IMarkVector &rArr)
Definition: wrtw8nds.cxx:1858
sal_Int32 GetFirstLineOffset() const
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
#define RES_TXTATR_REFMARK
Definition: hintids.hxx:136
virtual const SwPosition & GetMarkEnd() const =0
static void InsUInt16(ww::bytes &rO, sal_uInt16 n)
Definition: wrtww8.cxx:1732
virtual void TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo) override
Definition: wrtww8.cxx:2007
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:53
bool GetAnnotationMarks(const SwWW8AttrIter &rAttrs, sal_Int32 nStt, sal_Int32 nEnd, IMarkVector &rArr)
Definition: wrtw8nds.cxx:1894
TOXTypes GetType() const
Definition: tox.hxx:663
SvtSaveOptions const m_aSaveOpt
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:723
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:351
SwTableBox * GetUpper()
Definition: swtable.hxx:362
virtual bool StartURL(const OUString &rUrl, const OUString &rTarget)=0
Output URL start.
css::text::RubyAdjust GetAdjustment() const
Definition: fmtruby.hxx:73
virtual void PrepareNewPageDesc(const SfxItemSet *pSet, const SwNode &rNd, const SwFormatPageDesc *pNewPgDescFormat, const SwPageDesc *pNewPgDesc)=0
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter()
Definition: breakit.hxx:62
#define ODF_FORMDATE
const SfxPoolItem & GetAttr() const
Definition: txatbase.hxx:159
OString const aName
void ExportPoolItemsToCHP(ww8::PoolItems &rItems, sal_uInt16 nScript, const SvxFontItem *pFont, bool bWriteCombChars=false)
Export the pool items to attributes (through an attribute output class).
Definition: ww8atr.cxx:212
virtual OUString GetFieldname() const =0
virtual void Redline(const SwRedlineData *pRedline)=0
Output redlining.
sal_Int32 nCurrentSwPos
Definition: wrtww8.hxx:1502
#define SAL_WARN(area, stream)
const SwCharFormat * GetCharFormat() const
Definition: paratr.hxx:98
Base class for WW8Export and DocxExport.
Definition: wrtww8.hxx:453
OUString GetMark(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static OUString lcl_getFieldCode(const IFieldmark *pFieldmark)
Definition: wrtw8nds.cxx:119
sal_Int32 SearchNext(sal_Int32 nStartPos)
Definition: wrtw8nds.cxx:249
SwRedlineTable::size_type nCurRedlinePos
Definition: wrtww8.hxx:1503
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:96
bool IsExportableAttr(sal_Int32 nSwPos) const
Definition: wrtw8nds.cxx:720
SvxFrameDirection GetCurrentPageDirection() const
Right to left?
Definition: wrtw8nds.cxx:1519
const SwFormatDrop & GetSwFormatDrop() const
Definition: wrtww8.hxx:1546
virtual const SwPosition & GetMarkStart() const =0
static OUString GetBookmarkName(sal_uInt16 nTyp, const OUString *pName, sal_uInt16 nSeqNo)
Find the bookmark name.
Definition: ww8atr.cxx:928
virtual void EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner)=0
End of the paragraph.
const SwTextTOXMark * GetTextTOXMark() const
Definition: tox.hxx:137
bool mbParaIsRTL
Definition: wrtww8.hxx:1505
const SwTextNode & GetNode() const
Definition: wrtww8.hxx:1553
bool IsInline() const
Is this frame inline (as character)
WriterSource GetWriterType() const
Get the type of frame that this wraps.
SectionType GetType() const
Definition: section.hxx:171
SwGrfNode * GetGrfNode()
Definition: ndgrf.hxx:155
MSWordAttrIter(const MSWordAttrIter &)=delete
static SwTextFormatColl & lcl_getFormatCollection(MSWordExportBase &rExport, const SwTextNode *pTextNode)
Delivers the right paragraph style.
Definition: wrtw8nds.cxx:1741
virtual void WriteHyperlinkData(const ::sw::mark::IFieldmark &rFieldmark)=0
static bool NoPageBreakSection(const SfxItemSet *pSet)
Definition: wrtw8nds.cxx:3024
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
If SwFormatDrop is a Client, it is the CharFormat that describes the font for the DropCaps...
Definition: paratr.hxx:50
const sal_uInt16 sprmPDcs
Definition: sprmids.hxx:390
virtual const SwRedlineTable & GetRedlineTable() const =0
void TOXMark(const SwTextNode &rNode, const SwTOXMark &rAttr)
Definition: wrtw8nds.cxx:1210
std::vector< ::sw::mark::IMark * > IMarkVector
Used to split the runs according to the bookmarks start and ends.
Definition: wrtww8.hxx:581
virtual void AppendBookmark(const OUString &rName)=0
void EndCommentOutput(const OUString &rName)
Definition: ww8atr.cxx:1881
void ClearOverridesFromSet(const SwFormatCharFormat &rFormat, SfxItemSet &rSet)
Remove properties from an SfxItemSet which a SwFormatCharFormat overrides.
#define RES_PAGEDESC
Definition: hintids.hxx:198
#define RES_BREAK
Definition: hintids.hxx:199
void OutAttr(sal_Int32 nSwPos, bool bWriteCombinedChars)
Definition: wrtw8nds.cxx:386
virtual void RestoreData() override
Restore what was saved in SaveData().
Definition: wrtww8.cxx:1992
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
bool IsTextAttr(sal_Int32 nSwPos) const
Definition: wrtw8nds.cxx:695
void OutputFlyFrame_Impl(const ww8::Frame &rFormat, const Point &rNdTopLeft) override
Output frames - the implementation.
Definition: wrtw8nds.cxx:3205
virtual bool EndURL(bool) override
Output URL end.
Definition: wrtw8nds.cxx:1138
virtual void WriteFormData(const ::sw::mark::IFieldmark &rFieldmark)=0
Write the data of the form field.
int OutAttrWithRange(const SwTextNode &rNode, sal_Int32 nPos)
Definition: wrtw8nds.cxx:1265
SwTableLine * GetUpper()
Definition: swtable.hxx:421
sal_Int32 nPos
bool IsTextNode() const
Definition: node.hxx:636
#define RES_CHRATR_GRABBAG
Definition: hintids.hxx:111
The class MSWordAttrIter is a helper class to build the Fkp.chpx.
Definition: wrtww8.hxx:1424
std::shared_ptr< WW8TableNodeInfo > Pointer_t
static void WriteLong(SvStream &rStrm, sal_Int32 nVal)
Definition: wrtww8.hxx:954
const SwPosition & GetPosition() const
Get the position this frame is anchored at.
bool IsInTable() const
Return whether currently exported node is in table.
Definition: wrtww8.cxx:2883
bool NeedTextNodeSplit(const SwTextNode &rNd, SwSoftPageBreakList &pList) const
Definition: wrtw8nds.cxx:2098
SwFrameFormat * GetFlyFormat() const
If node is in a fly return the respective format.
Definition: node.cxx:710
aStr
SwCharFormat * GetCharFormat()
Definition: txtatr2.cxx:230
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1273
const sal_uInt16 sprmCHpsPos
Definition: sprmids.hxx:303
virtual void AppendSection(const SwPageDesc *pPageDesc, const SwSectionFormat *pFormat, sal_uLong nLnNum)=0
const sal_uInt8 ND_HAS_NEXT_LAYNODE
Definition: ndtyp.hxx:64
virtual void EndRun(const SwTextNode *pNode, sal_Int32 nPos, bool bLastRun=false)=0
End of the text run.
SwRect FindPageFrameRect() const
Definition: node.cxx:1172
virtual void EmptyParagraph() override
Empty paragraph.
Definition: wrtw8nds.cxx:3019
std::unique_ptr< WW8_WrPlcPn > m_pChpPlc
Definition: wrtww8.hxx:497
sal_uInt16 Which() const
SvxFrameDirection TrueFrameDirection(const SwFrameFormat &rFlyFormat) const
Right to left?
Definition: wrtw8nds.cxx:1566
SdrObject * FindRealSdrObject()
Definition: atrfrm.cxx:2686
OUString ConvertURL(const OUString &rUrl, bool bAbsoluteOut)
Definition: wrtw8nds.cxx:874
IMarkVector m_rSortedBookmarksStart
Definition: wrtww8.hxx:582
SwDoc * m_pDoc
Definition: wrtww8.hxx:572
#define ODF_ID_PARAM
virtual MSWordExportBase & GetExport()=0
Return the right export class.
static OUString encode(OUString const &rText, Part ePart, EncodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1308
std::vector< aBookmarkPair > m_aImplicitBookmarks
Definition: wrtww8.hxx:491
virtual void OutputFlyFrame_Impl(const ww8::Frame &rFormat, const Point &rNdTopLeft)=0
Output frames - the implementation.
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:843
#define ODF_FORMDROPDOWN
bool IsAnchorLinkedToThisNode(sal_uLong nNodePos)
Definition: wrtw8nds.cxx:551
virtual void WritePostitFieldReference()
for docx w:commentReference
virtual void FieldVanish(const OUString &rText, ww::eField eType) override
Definition: wrtw8nds.cxx:1184
OUString m_sFontFamily
virtual void OutputFKP(bool)
Output FKP (Formatted disK Page) - necessary for binary formats only.
bool RequiresImplicitBookmark()
Definition: wrtw8nds.cxx:763
Base class of the Writer document model elements.
Definition: node.hxx:79
static OUString decode(OUString const &rText, DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)